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

This commit is contained in:
Airistotal
2015-07-29 16:24:27 -05:00
93 changed files with 3665 additions and 3285 deletions
@@ -1,4 +1,7 @@
.venv/
contrib/
client/
database/
doc/patch.py
doc/source/conf.py
lib/galaxy/model/migrate/versions/
+1 -1
View File
@@ -2,7 +2,7 @@
set -e
flake8 --exclude database/,.venv/,`paste -sd, .ci/pep8_sources.txt` .
flake8 --exclude `paste -sd, .ci/flake8_blacklist.txt` .
# Look for obviously broken stuff lots more places.
flake8 --select=E901,E902,F821,F822,F823,F831 --exclude lib/galaxy/util/pastescript/serve.py,lib/pkg_resources.py lib/ test/{api,unit}
+2 -1
View File
@@ -22,5 +22,6 @@ module.exports = function(grunt) {
// see the sub directory grunt-tasks/ for individual task definitions
grunt.loadTasks( 'grunt-tasks' );
grunt.registerTask( 'default', [ 'uglify' ] );
// note: 'handlebars' *not* 'templates' since handlebars doesn't call uglify
grunt.registerTask( 'default', [ 'handlebars', 'uglify' ] );
};
+13
View File
@@ -33,6 +33,19 @@ This will:
2. generate source maps and place them in static/maps
Templates
=========
You can change and recompile the templates by using:
grunt templates
This will:
1. recompile the templates in client/galaxy/scripts/templates to client/galaxy/scripts/templates/compiled
2. minify and generate source maps for the compiled templates
Changing Styles/CSS
===================
+1 -1
View File
@@ -30,7 +30,7 @@
"jstree": "~3.0.9",
"jquery-ui": "git://github.com/jquery/jquery-ui.git#~1.11.2",
"threedubmedia.jquery.event": "*",
"handlebars": "~2.0.0",
"handlebars": "~3.0.0",
"jquery-migrate": "~1.2.1",
"requirejs": "~2.1.17"
},
File diff suppressed because it is too large Load Diff
@@ -568,7 +568,8 @@ var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).exte
*/
createList : function( name ){
var creator = this,
url = '/api/histories/' + this.historyId + '/contents/dataset_collections';
root = ( window.Galaxy && Galaxy.options.root )? Galaxy.options.root : '/',
url = root + 'api/histories/' + this.historyId + '/contents/dataset_collections';
//TODO: use ListPairedCollection.create()
var ajaxData = {
@@ -143,17 +143,21 @@ var HistoryPanel = _super.extend(
*/
_setUpListeners : function(){
_super.prototype._setUpListeners.call( this );
this.on( 'error', function( model, xhr, options, msg, details ){
this.errorHandler( model, xhr, options, msg, details );
});
this.on( 'loading-done', function(){
//TODO:?? if( this.collection.length ){
if( !this.views.length ){
this.trigger( 'empty-history', this );
this.on({
error : function( model, xhr, options, msg, details ){
this.errorHandler( model, xhr, options, msg, details );
},
'loading-done' : function(){
//TODO:?? if( this.collection.length ){
if( !this.views.length ){
this.trigger( 'empty-history', this );
}
},
'views:ready view:attached view:removed' : function( view ){
this._renderSelectButton();
}
});
// this.on( 'all', function(){ console.debug( arguments ); });
},
// ------------------------------------------------------------------------ loading history/hda models
@@ -304,20 +308,34 @@ var HistoryPanel = _super.extend(
/** In this override, add a btn to toggle the selectors */
_buildNewRender : function(){
var $newRender = _super.prototype._buildNewRender.call( this );
//if( this.views.length && this.multiselectActions().length ){
if( this.multiselectActions().length ){
$newRender.find( '.controls .actions' ).prepend( this._renderSelectButton() );
}
this._renderSelectButton( $newRender );
return $newRender;
},
/** button for starting select mode */
_renderSelectButton : function( $where ){
$where = $where || this.$el;
// do not render selector option if no actions
if( !this.multiselectActions().length ){
return null;
}
// do not render (and remove even) if nothing to select
if( !this.views.length ){
this.hideSelectors();
$where.find( '.controls .actions .show-selectors-btn' ).remove();
return null;
}
// don't bother rendering if there's one already
var $existing = $where.find( '.controls .actions .show-selectors-btn' );
if( $existing.size() ){
return $existing;
}
return faIconButton({
title : _l( 'Operations on multiple datasets' ),
classes : 'show-selectors-btn',
faIcon : 'fa-check-square-o'
});
}).prependTo( $where.find( '.controls .actions' ) );
},
// ------------------------------------------------------------------------ sub-views
@@ -398,9 +416,9 @@ var HistoryPanel = _super.extend(
if( store ){
this.storage.set( 'show_deleted', show );
}
this.trigger( 'show-hidden', show );
//TODO:?? to events on storage('change:show_deleted')
this.renderItems();
this.trigger( 'show-deleted', show );
return this.showDeleted;
},
@@ -416,9 +434,9 @@ var HistoryPanel = _super.extend(
if( store ){
this.storage.set( 'show_hidden', show );
}
this.trigger( 'show-hidden', show );
//TODO:?? to events on storage('change:show_deleted')
this.renderItems();
this.trigger( 'show-hidden', show );
return this.showHidden;
},
@@ -371,6 +371,7 @@ var ListPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(
} else {
panel._renderEmptyMessage( $whereTo ).show();
}
panel.trigger( 'views:ready', panel.views );
return panel.views;
},
+1 -1
View File
@@ -262,7 +262,7 @@ var Tool = Backbone.Model.extend({
// Run job and resolve run_deferred to tool outputs.
$.when(ss_deferred.go()).then(function(result) {
run_deferred.resolve(new data.DatasetCollection().reset(result));
run_deferred.resolve(new data.DatasetCollection(result));
});
return run_deferred;
}
+3 -3
View File
@@ -68,9 +68,9 @@ var View = Backbone.View.extend({
this.$text.on('keydown', function (e) {
var v = e.which;
pressed[v] = true;
if (!(v == 8 || v == 9 || v == 13 || v == 37 || v == 39 || (v >= 48 && v <= 57)
|| (v == 190 && $(this).val().indexOf('.') == -1 && self.options.precise)
|| (v == 189 && $(this).val().indexOf('-') == -1)
if (!(v == 8 || v == 9 || v == 13 || v == 37 || v == 39 || (v >= 48 && v <= 57) || (v >= 96 && v <= 105)
|| ((v == 190 || v == 110) && $(this).val().indexOf('.') == -1 && self.options.precise)
|| ((v == 189 || v == 109) && $(this).val().indexOf('-') == -1)
|| pressed[91] || pressed[17])) {
event.preventDefault();
}
@@ -1,238 +0,0 @@
#!/usr/bin/env python
# Script requires handlebars compiler be installed; use node package manager
# to install handlebars.
"""%prog [options] [ specific .handlebars or .html template file to compile ]
Compiles handlebars templates into javascript for better load times and performance.
Handlebars compilation errors will print to stderr.
NOTE!: you will need node.js, npm, and handlebars (installed from npm) in order to compile templates
See http://handlebarsjs.com/precompilation.html for more info.
Should be called from the $GLX_ROOT/static/scripts/templates directory.
Compiled templates will be written to the compiled/ directory.
If the --multi-ext option is passed a file extension string, the script will:
* search for *.<extension> in the current directory,
* extract each '<script type="text/template"> from the file and write them into a new handlebars file
named using the id of the script tag (eg. id="undeleteMsg" -> undeleteMsg.handlebars)
* these new handlebars scripts will be compiled along with any other handlebars templates in the dir
additionally for each of those files, the script will:
* extract each '<script type="text/javascript"> from the file and write them ALL into a single js file
named using the prefix 'helpers-' and the basename of the enclosing file
(eg. common-templates.html -> helpers-common-templates.js )
* these new handlebars scripts will be compiled along with any other handlebars templates in the dir
These files can be included as if they were templates (eg. h.templates( 'helpers-common-templates' ) )
This hopefully will allow both multiple templates and their associated Handlebars helper functions to be
included in one file.
Currently, this works (best?) if:
* the multiple templates are within one html file
* each template is enclosed in a <script> tag with type="text/template" and some id attribute
* each helper fn is enclosed in a <script> tag with type="text/javascript" and some id attribute
e.g. <script type="text/template" id="history-deletedMsg" class="template">Deleted {{ msg }}</script>
"""
# ------------------------------------------------------------------------------
TODO = """
remove intermediate, handlebars step of multi->handlebars->compiled/.js (if handlebars does stdin)
"""
import sys
from glob import glob
from subprocess import call
import os
from optparse import OptionParser
import re
import logging as log
log.basicConfig(
# level=log.DEBUG,
name=__name__
)
COMPILED_DIR = 'compiled'
COMPILED_EXT = '.js'
COMPILE_CMD_STR = "handlebars %s -f %s"
COMPILE_MINIMIZE_SWITCH = ' -m'
TEMPLATE_TAG = 'script'
TEMPLATE_TYPE = 'text/template'
HELPER_TYPE = 'text/javascript'
# both of these are off by default for backward compat
DEFAULT_MINIMIZATION = False
DEFAULT_MULTI_EXT = None # '.html'
# ------------------------------------------------------------------------------
def parse_html_tag_attrs( string ):
attrs = {}
for match in re.finditer( r'(?P<key>\w+?)=[\'|\"](?P<val>.*?)[\'|\"]', string, re.DOTALL | re.MULTILINE ):
match = match.groupdict()
key = match[ 'key' ]
val = match[ 'val' ]
attrs[ key ] = val
return attrs
def split_on_html_tag( string, tag ):
tag_pattern = r'<%s\s*(?P<attrs>.*?)>(?P<body>.*?)</%s>' % ( tag, tag )
log.debug( tag_pattern )
tag_pattern = re.compile( tag_pattern, re.MULTILINE | re.DOTALL )
found_list = re.findall( tag_pattern, string )
for attrs, body in found_list:
yield ( parse_html_tag_attrs( attrs ), body )
def filter_on_tag_type( generator, type_attr_to_match ):
for attrs, body in generator:
log.debug( 'attrs: %s', str( attrs ) )
if( ( 'type' in attrs )
and ( attrs[ 'type' ] == type_attr_to_match ) ):
yield attrs, body
# ------------------------------------------------------------------------------
def break_multi_template( multi_template_filename ):
"""parse the multi template, writing each template into a new handlebars tmpl and returning their names"""
template_filenames = []
# parse the multi template
print "\nBreaking multi-template file %s into individual templates and helpers:" % ( multi_template_filename )
with open( multi_template_filename, 'r' ) as multi_template_file:
multi_template_file_text = multi_template_file.read()
# write a template file for each template (name based on id in tag)
tag_generator = split_on_html_tag( multi_template_file_text, TEMPLATE_TAG )
for attrs, template_text in filter_on_tag_type( tag_generator, TEMPLATE_TYPE ):
if( 'id' not in attrs ):
log.warning( 'Template has no "id". attrs: %s' % ( str( attrs ) ) )
continue
template_id = attrs[ 'id' ]
template_text = template_text.strip()
handlebar_template_filename = template_id + '.handlebars'
with open( handlebar_template_filename, 'w' ) as handlebar_template_file:
handlebar_template_file.write( template_text )
log.debug( "%s\n%s\n", template_id, template_text )
template_filenames.append( handlebar_template_filename )
# write all helpers to a single 'helper-' prefixed js file in the compilation dir
helper_fns = []
# same tag, different type
tag_generator = split_on_html_tag( multi_template_file_text, TEMPLATE_TAG )
for attrs, helper_text in filter_on_tag_type( tag_generator, HELPER_TYPE ):
helper_text = helper_text.strip()
print '(helper):', ( attrs[ 'id' ] if 'id' in attrs else '(No id)' )
helper_fns.append( helper_text )
if helper_fns:
# prefix original filename (in compiled dir) and write all helper funcs to that file
helper_filename = 'helpers-' + os.path.splitext( multi_template_filename )[0] + '.js'
helper_filename = os.path.join( COMPILED_DIR, helper_filename )
with open( helper_filename, 'w' ) as helper_file:
helper_file.write( '\n'.join( helper_fns ) )
print '(helper functions written to %s)' % helper_filename
print '\n'.join( template_filenames )
return template_filenames
# ------------------------------------------------------------------------------
def compile_template( template_filename, minimize=False ):
"""compile the given template file (optionally minimizing the js) using subprocess.
Use the basename of the template file for the outputed js.
"""
template_basename = os.path.splitext( os.path.split( template_filename )[1] )[0]
compiled_filename = os.path.join( COMPILED_DIR, template_basename + COMPILED_EXT )
command_string = COMPILE_CMD_STR % ( template_filename, compiled_filename )
if minimize:
command_string += COMPILE_MINIMIZE_SWITCH
print command_string
return call( command_string, shell=True )
# ------------------------------------------------------------------------------
def main( options, args ):
"""Break multi template files into single templates, compile all single templates.
If args, compile that as a list of specific handlebars and/or multi template files.
"""
print "(Call this script with the '-h' option for more help)"
handlebars_templates = []
# If specific scripts specified on command line, just compile them,
if len( args ) >= 1:
handlebars_templates = filter( lambda( x ): x.endswith( '.handlebars' ), args )
# otherwise compile all in the current dir
else:
handlebars_templates = glob( '*.handlebars' )
# if desired, break up any passed-in or found multi template files
# adding the names of the new single templates to those needing compilation
multi_template_template_filenames = []
if options.multi_ext:
multi_templates = []
if len( args ) >= 1:
multi_templates = filter( lambda( x ): x.endswith( options.multi_ext ), args )
else:
multi_templates = glob( '*' + options.multi_ext )
for multi_template_filename in multi_templates:
multi_template_template_filenames.extend( break_multi_template( multi_template_filename ) )
# unique filenames only (Q&D)
handlebars_templates = list( set( handlebars_templates + multi_template_template_filenames ) )
# compile the templates
print "\nCompiling templates:"
filenames_w_possible_errors = []
for handlebars_template in handlebars_templates:
shell_ret = compile_template( handlebars_template, options.minimize )
if shell_ret:
filenames_w_possible_errors.append( handlebars_template )
# report any possible errors
if filenames_w_possible_errors:
print "\nThere may have been errors on the following files:"
print ',\n'.join( filenames_w_possible_errors )
print "\nCall this script with the '-h' for more help"
# delete multi template intermediate files
if options.remove_intermediate:
print "\nCleaning up intermediate multi-template template files:"
for filename in multi_template_template_filenames:
try:
print 'removing', filename
os.remove( filename )
except Exception, exc:
print exc
# ------------------------------------------------------------------------------
if __name__ == '__main__':
optparser = OptionParser( usage=__doc__ )
optparser.add_option( '-m', '--minimize', dest='minimize', action='store_true', default=DEFAULT_MINIMIZATION,
help=( 'minimize compiled template scripts via handlebars '
+ '(defaults to %s)' % DEFAULT_MINIMIZATION ) )
optparser.add_option( '--multi-ext', dest='multi_ext', metavar="FILE_EXTENSION", default=DEFAULT_MULTI_EXT,
help=( 'indicates that files ending with the given string contain multiple '
+ 'templates and the script should break those into individual '
+ 'handlebars templates (defaults to "%s")' ) % DEFAULT_MULTI_EXT )
optparser.add_option( '--no-remove', action='store_false', dest='remove_intermediate', default=True,
help=( 'remove intermediate *.handlebars files when using multiple template'
+ 'files (defaults to "True")' ) )
( options, args ) = optparser.parse_args()
sys.exit( main( options, args ) )
@@ -1,6 +1,7 @@
(function() {
var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
templates['panel_section'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
this["Handlebars"] = this["Handlebars"] || {};
this["Handlebars"]["templates"] = this["Handlebars"]["templates"] || {};
this["Handlebars"]["templates"]["panel_section"] = Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
var helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression;
return "<div class=\"toolSectionTitle\" id=\"title_"
@@ -10,5 +11,4 @@ templates['panel_section'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":f
+ "</span></a>\n</div>\n<div id=\""
+ alias3(((helper = (helper = helpers.id || (depth0 != null ? depth0.id : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"id","hash":{},"data":data}) : helper)))
+ "\" class=\"toolSectionBody\" style=\"display: none; \">\n <div class=\"toolSectionBg\"></div>\n<div>";
},"useData":true});
})();
},"useData":true});
@@ -1,6 +1,7 @@
(function() {
var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
templates['tool_form'] = template({"1":function(depth0,helpers,partials,data) {
this["Handlebars"] = this["Handlebars"] || {};
this["Handlebars"]["templates"] = this["Handlebars"]["templates"] || {};
this["Handlebars"]["templates"]["tool_form"] = Handlebars.template({"1":function(depth0,helpers,partials,data) {
var stack1, helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression;
return " <div class=\"form-row\">\n <label for=\""
@@ -24,5 +25,4 @@ templates['tool_form'] = template({"1":function(depth0,helpers,partials,data) {
+ " </div>\n <div class=\"form-row form-actions\">\n <input type=\"submit\" class=\"btn btn-primary\" name=\"runtool_btn\" value=\"Execute\">\n</div>\n<div class=\"toolHelp\">\n <div class=\"toolHelpBody\">"
+ alias3(((helper = (helper = helpers.help || (depth0 != null ? depth0.help : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"help","hash":{},"data":data}) : helper)))
+ "</div>\n</div>";
},"useData":true});
})();
},"useData":true});
@@ -1,6 +1,7 @@
(function() {
var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
templates['tool_link'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
this["Handlebars"] = this["Handlebars"] || {};
this["Handlebars"]["templates"] = this["Handlebars"]["templates"] || {};
this["Handlebars"]["templates"]["tool_link"] = Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
var helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression;
return "<a class=\""
@@ -15,5 +16,4 @@ templates['tool_link'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":funct
+ alias3(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"name","hash":{},"data":data}) : helper)))
+ "</a> "
+ alias3(((helper = (helper = helpers.description || (depth0 != null ? depth0.description : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"description","hash":{},"data":data}) : helper)));
},"useData":true});
})();
},"useData":true});
@@ -1,6 +1,7 @@
(function() {
var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
templates['tool_search'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
this["Handlebars"] = this["Handlebars"] || {};
this["Handlebars"]["templates"] = this["Handlebars"]["templates"] || {};
this["Handlebars"]["templates"]["tool_search"] = Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
var helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression;
return "<input type=\"text\" name=\"query\" placeholder=\""
@@ -8,5 +9,4 @@ templates['tool_search'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":fun
+ "\" id=\"tool-search-query\" autocomplete=\"off\" class=\"search-query parent-width\" />\n<a id=\"search-clear-btn\" title=\"clear search (esc)\"> </a>\n<img src=\""
+ alias3(((helper = (helper = helpers.spinner_url || (depth0 != null ? depth0.spinner_url : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"spinner_url","hash":{},"data":data}) : helper)))
+ "\" id=\"search-spinner\" class=\"search-spinner\"/>\n";
},"useData":true});
})();
},"useData":true});
+48 -48
View File
@@ -1,5 +1,5 @@
/**
* Visualization and components for Sweepster, a visualization for exploring a tool's parameter space via
* Visualization and components for Sweepster, a visualization for exploring a tool's parameter space via
* genomic visualization.
*/
@@ -7,7 +7,7 @@ define(["libs/underscore", "libs/d3", "viz/trackster/util", "viz/visualization",
function(_, d3, util, visualization, tracks, tools, data, config, mod_icon_btn) {
/**
* A collection of tool input settings. Object is useful for keeping a list of settings
* A collection of tool input settings. Object is useful for keeping a list of settings
* for future use without changing the input's value and for preserving inputs order.
*/
var ToolInputsSettings = Backbone.Model.extend({
@@ -16,7 +16,7 @@ var ToolInputsSettings = Backbone.Model.extend({
values: null
}
});
/**
* Tree for a tool's parameters.
*/
@@ -25,7 +25,7 @@ var ToolParameterTree = Backbone.Model.extend({
tool: null,
tree_data: null
},
initialize: function(options) {
// Set up tool parameters to work with tree.
var self = this;
@@ -109,7 +109,7 @@ var ToolParameterTree = Backbone.Model.extend({
};
});
}
// Recurse to handle other parameters.
return _.map(settings, function(setting) {
return {
@@ -141,7 +141,7 @@ var ToolParameterTree = Backbone.Model.extend({
get_num_leaves: function() {
return this.get_tree_params().reduce(function(memo, param) { return memo * param.get_samples().length; }, 1);
},
/**
* Returns array of ToolInputsSettings objects based on a node and its subtree.
*/
@@ -159,7 +159,7 @@ var ToolParameterTree = Backbone.Model.extend({
cur_node = cur_node.parent;
}
}
// Walk subtree starting at clicked node to get full list of settings.
var self = this,
get_settings = function(node, settings) {
@@ -168,7 +168,7 @@ var ToolParameterTree = Backbone.Model.extend({
if (node.param) {
settings[node.param.get('name')] = node.value;
}
if (!node.children) {
// At leaf node, so return settings.
return new ToolInputsSettings({
@@ -182,10 +182,10 @@ var ToolParameterTree = Backbone.Model.extend({
}
},
all_settings = get_settings(target_node, fixed_settings);
// If user clicked on leaf, settings is a single dict. Convert to array for simplicity.
if (!_.isArray(all_settings)) { all_settings = [ all_settings ]; }
return all_settings;
},
@@ -235,7 +235,7 @@ var ToolParameterTree = Backbone.Model.extend({
* Returns a list of parameters used in tree.
*/
toJSON: function() {
// FIXME: returning and jsonifying complete param causes trouble on the server side,
// FIXME: returning and jsonifying complete param causes trouble on the server side,
// so just use essential attributes for now.
return this.get_tree_params().map(function(param) {
return {
@@ -255,7 +255,7 @@ var SweepsterTrack = Backbone.Model.extend({
settings: null,
regions: null
},
initialize: function(options) {
this.set('regions', options.regions);
if (options.track) {
@@ -272,7 +272,7 @@ var SweepsterTrack = Backbone.Model.extend({
var this_settings = this.get('settings'),
other_settings = a_track.get('settings');
for (var prop in this_settings) {
if (!other_settings[prop] ||
if (!other_settings[prop] ||
this_settings[prop] !== other_settings[prop]) {
return false;
}
@@ -316,8 +316,8 @@ var SweepsterVisualization = visualization.Visualization.extend({
this.set('tool_with_samplable_inputs', tool_with_samplable_inputs);
// Remove complex parameters for now.
tool_with_samplable_inputs.remove_inputs( [ 'data', 'hidden_data', 'conditional', 'text' ] );
this.set('parameter_tree', new ToolParameterTree({
this.set('parameter_tree', new ToolParameterTree({
tool: tool_with_samplable_inputs,
config: options.tree_config
}));
@@ -445,9 +445,9 @@ var SweepsterTrackView = Backbone.View.extend({
var ToolInputValOrSweepView = Backbone.View.extend({
// Template for rendering sweep inputs:
number_input_template: '<div class="form-row-input sweep">' +
number_input_template: '<div class="form-row-input sweep">' +
'<input class="min" type="text" size="6" value="<%= min %>"> - ' +
'<input class="max" type="text" size="6" value="<%= max %>">' +
'<input class="max" type="text" size="6" value="<%= max %>">' +
' samples: <input class="num_samples" type="text" size="1" value="<%= num_samples %>">' +
'</div>',
@@ -471,16 +471,16 @@ var ToolInputValOrSweepView = Backbone.View.extend({
// Add row for parameter sweep inputs.
if (input instanceof tools.IntegerToolParameter) {
sweep_inputs_row = $(_.template(this.number_input_template, this.model.toJSON()));
sweep_inputs_row = $( _.template(this.number_input_template)(this.model.toJSON()) );
}
else if (input instanceof tools.SelectToolParameter) {
var options = _.map(this.$el.find('select option'), function(option) {
return $(option).val();
}),
options_text = options.join(', ');
sweep_inputs_row = $(_.template(this.select_input_template, {
sweep_inputs_row = $( _.template(this.select_input_template)({
options: options_text
}));
}) );
}
sweep_inputs_row.insertAfter(single_input_row);
@@ -497,7 +497,7 @@ var ToolInputValOrSweepView = Backbone.View.extend({
$(this).hide();
self.$el.find('.icon-button.toggle').show();
}
},
{
title: 'Remove parameter from tree',
@@ -511,9 +511,9 @@ var ToolInputValOrSweepView = Backbone.View.extend({
self.$el.find('.icon-button.plus-button').show();
}
}
],
],
{
});
this.$el.prepend(menu.$el);
@@ -568,12 +568,12 @@ var ToolParameterTreeDesignView = Backbone.View.extend({
*/
var ToolParameterTreeView = Backbone.View.extend({
className: 'tool-parameter-tree',
initialize: function(options) {
// When tree data changes, re-render.
this.model.on('change:tree_data', this.render, this);
},
render: function() {
// Start fresh.
this.$el.children().remove();
@@ -640,7 +640,7 @@ var ToolParameterTreeView = Backbone.View.extend({
.on('mouseout', function() {
node.style('fill', '#000');
});
node.append("circle")
.attr("r", 9);
@@ -658,13 +658,13 @@ var ToolParameterTreeView = Backbone.View.extend({
var SweepsterVisualizationView = Backbone.View.extend({
className: 'Sweepster',
helpText:
helpText:
'<div><h4>Getting Started</h4>' +
'<ol><li>Create a parameter tree by using the icons next to the tool\'s parameter names to add or remove parameters.' +
'<li>Adjust the tree by using parameter inputs to select min, max, and number of samples' +
'<li>Run the tool with different settings by clicking on tree nodes' +
'</ol></div>',
initialize: function(options) {
this.canvas_manager = new visualization.CanvasManager(this.$el.parents('body'));
this.tool_param_tree_view = new ToolParameterTreeView({ model: this.model.get('parameter_tree') });
@@ -680,7 +680,7 @@ var SweepsterVisualizationView = Backbone.View.extend({
});
// Set block, reverse strand block colors; these colors will be used for all tracks.
this.config = config.ConfigSettingCollection.from_models_and_saved_values(
this.config = config.ConfigSettingCollection.from_models_and_saved_values(
[
{ key: 'name', label: 'Name', type: 'text', default_value: '' },
{ key: 'a_color', label: 'A Color', type: 'color', default_value: "#FF0000" },
@@ -693,7 +693,7 @@ var SweepsterVisualizationView = Backbone.View.extend({
], {}
);
},
render: function() {
// Render tree design view in left panel.
var tree_design_view = new ToolParameterTreeDesignView({
@@ -749,7 +749,7 @@ var SweepsterVisualizationView = Backbone.View.extend({
[
// Save.
/*
{ icon_class: 'disk--arrow', title: 'Save', on_click: function() {
{ icon_class: 'disk--arrow', title: 'Save', on_click: function() {
// Show saving dialog box
show_modal("Saving...", "progress");
@@ -760,8 +760,8 @@ var SweepsterVisualizationView = Backbone.View.extend({
'has_changes': false
});
})
.error(function() {
show_modal( "Could Not Save", "Could not save visualization. Please try again later.",
.error(function() {
show_modal( "Could Not Save", "Could not save visualization. Please try again later.",
{ "Close" : hide_modal } );
});
} },
@@ -772,14 +772,14 @@ var SweepsterVisualizationView = Backbone.View.extend({
title: 'Set display mode'
},
// Close viz.
{
icon_class: 'cross-circle',
title: 'Close',
on_click: function() {
{
icon_class: 'cross-circle',
title: 'Close',
on_click: function() {
window.location = "${h.url_for( controller='visualization', action='list' )}";
}
}
}
],
],
{
tooltip_config: {placement: 'bottom'}
});
@@ -797,13 +797,13 @@ var SweepsterVisualizationView = Backbone.View.extend({
});
make_popupmenu(menu.$el.find('.chevron-expand'), mode_mapping);
menu.$el.attr("style", "float: right");
$("#right .unified-panel-header-inner").append(menu.$el);
},
get_base_color: function(base) {
return this.config.get_value(base.toLowerCase() + '_color') ||
return this.config.get_value(base.toLowerCase() + '_color') ||
this.config.get_value('n_color');
},
@@ -857,7 +857,7 @@ var SweepsterVisualizationView = Backbone.View.extend({
},
/**
* Sets up handling when tree nodes are clicked. When a node is clicked, the tool is run for each of
* Sets up handling when tree nodes are clicked. When a node is clicked, the tool is run for each of
* the settings defined by the node's subtree and tracks are added for each run.
*/
handle_node_clicks: function() {
@@ -875,11 +875,11 @@ var SweepsterVisualizationView = Backbone.View.extend({
// Do not allow 10+ jobs to be run.
if (all_settings.length >= 10) {
show_modal("Whoa there cowboy!",
show_modal("Whoa there cowboy!",
"You clicked on a node to try " + self.model.get('tool').get('name') +
" with " + all_settings.length +
" different combinations of settings. You can only run 10 jobs at a time.",
{
{
"Ok": function() { hide_modal(); run_jobs_deferred.resolve(false); }
});
}
@@ -901,7 +901,7 @@ var SweepsterVisualizationView = Backbone.View.extend({
self.add_track(pm_track);
return pm_track;
});
// For each track, run tool using track's settings and update track.
_.each(new_tracks, function(pm_track, index) {
setTimeout(function() {
@@ -915,7 +915,7 @@ var SweepsterVisualizationView = Backbone.View.extend({
track_config = dataset.get('track_config');
// Set dataset to be the tool's output.
track_config.dataset = dataset;
// Set tool to null so that it is not unpacked; unpacking it messes with
// Set tool to null so that it is not unpacked; unpacking it messes with
// the tool parameters and parameter tree.
track_config.tool = null;
@@ -924,11 +924,11 @@ var SweepsterVisualizationView = Backbone.View.extend({
// Create and add track for output dataset.
var track_obj = tracks.object_from_template(track_config, self, null);
track_obj.init_for_tool_data();
pm_track.set('track', track_obj);
});
}, index * 10000);
});
});
});
});
}
+59
View File
@@ -0,0 +1,59 @@
/**
* Grunt task to compile templates.
* @param {Object} grunt main grunt file
* @return {Function} callback to build this task
*/
module.exports = function( grunt ){
"use strict";
var app = grunt.config.get( 'app' ),
paths = grunt.config.get( 'paths' );
grunt.config( 'handlebars', {
'default' : {
files: [{
expand : true,
cwd : paths.srcSymlink + '/templates',
src : '**/*.handlebars',
dest : paths.srcSymlink + '/templates/compiled',
ext : '.js'
}],
options : {
namespace : 'Handlebars.templates',
// generates the key under the namespace above where the template fns are accessed
processName : function( filepath ){
filepath = filepath.match( /.*\/(\w+)\.handlebars/ ).pop();
return filepath;
},
wrapped : true
}
}
});
grunt.registerTask( 'templates', function(){
// compile then compress
grunt.task.run( 'handlebars' );
grunt.config( 'uglify.target.files', [{
expand : true,
cwd : paths.srcSymlink + '/templates/compiled',
src : '**/*.js',
dest : paths.dist + '/templates/compiled'
}]);
grunt.task.run( 'uglify' );
});
// -------------------------------------------------------------------------- watch & compile
// grunt.config( 'watch', {
// watch: {
// // watch for changes in the src dir
// files: [ paths.srcSymlink + '/**' ],
// tasks: [ 'uglify' ],
// options: {
// spawn: false
// }
// }
// });
// --------------------------------------------------------------------------
grunt.loadNpmTasks( 'grunt-contrib-handlebars' );
};
+1
View File
@@ -11,6 +11,7 @@
"grunt-cli": "^0.1.13",
"grunt-contrib-clean": "^0.6.0",
"grunt-contrib-copy": "^0.5.0",
"grunt-contrib-handlebars": "^0.10.2",
"grunt-contrib-less": "^1.0.1",
"grunt-contrib-uglify": "^0.8.0",
"grunt-contrib-watch": "^0.6.1",
+1 -1
View File
@@ -106,7 +106,7 @@
<display file="igb/gtf.xml" />
</datatype>
<datatype extension="toolshed.gz" type="galaxy.datatypes.binary:Binary" mimetype="multipart/x-gzip" subclass="True" />
<datatype extension="h5" type="galaxy.datatypes.binary:Binary" mimetype="application/octet-stream" subclass="True" />
<datatype extension="h5" type="galaxy.datatypes.binary:Binary" mimetype="application/octet-stream" subclass="True" display_in_upload="True"/>
<datatype extension="html" type="galaxy.datatypes.images:Html" mimetype="text/html"/>
<datatype extension="interval" type="galaxy.datatypes.interval:Interval" display_in_upload="true" description="File must start with definition line in the following format (columns may be in any order)." >
<converter file="interval_to_bed_converter.xml" target_datatype="bed"/>
+10 -3
View File
@@ -643,6 +643,12 @@ nglims_config_file = tool-data/nglims.yaml
# make the Galaxy instance susceptible to XSS attacks initiated by your users.
#sanitize_all_html = True
# Whitelist sanitization file.
# Datasets created by tools listed in this file are trusted and will not have
# their HTML sanitized on display. This can be manually edited or manipulated
# through the Admin control panel -- see "Manage Display Whitelist"
#sanitize_whitelist_file = config/sanitize_whitelist.txt
# By default Galaxy will serve non-HTML tool output that may potentially
# contain browser executable JavaScript content as plain text. This will for
# instance cause SVG datasets to not render properly and so may be disabled
@@ -973,9 +979,10 @@ use_interactive = True
# Very large metadata values can cause Galaxy crashes. This will allow
# limiting the maximum metadata key size (in bytes used in memory, not the end
# result database value size) Galaxy will attempt to save with a dataset. 0 to
# disable this feature. 5000000 seems to be a reasonable size.
#max_metadata_value_size = 0
# result database value size) Galaxy will attempt to save with a dataset. Use
# 0 to disable this feature. The default is 5MB, but as low as 1MB seems to be
# a reasonable size.
#max_metadata_value_size = 5242880
# If (for example) you run on a cluster and your datasets (by default,
# database/files/) are mounted read-only, this option will override tool output
+14 -2
View File
@@ -146,7 +146,7 @@ class Configuration( object ):
self.tool_secret = kwargs.get( "tool_secret", "" )
self.id_secret = kwargs.get( "id_secret", "USING THE DEFAULT IS NOT SECURE!" )
self.retry_metadata_internally = string_as_bool( kwargs.get( "retry_metadata_internally", "True" ) )
self.max_metadata_value_size = int( kwargs.get( "max_metadata_value_size", 0 ) )
self.max_metadata_value_size = int( kwargs.get( "max_metadata_value_size", 5242880 ) )
self.use_remote_user = string_as_bool( kwargs.get( "use_remote_user", "False" ) )
self.normalize_remote_user_email = string_as_bool( kwargs.get( "normalize_remote_user_email", "False" ) )
self.remote_user_maildomain = kwargs.get( "remote_user_maildomain", None )
@@ -252,6 +252,8 @@ class Configuration( object ):
self.log_actions = string_as_bool( kwargs.get( 'log_actions', 'False' ) )
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.serve_xss_vulnerable_mimetypes = string_as_bool( kwargs.get( 'serve_xss_vulnerable_mimetypes', False ) )
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" ) )
@@ -436,7 +438,7 @@ class Configuration( object ):
self.fluent_log = string_as_bool( kwargs.get( 'fluent_log', False ) )
self.fluent_host = kwargs.get( 'fluent_host', 'localhost' )
self.fluent_port = int( kwargs.get( 'fluent_port', 24224 ) )
# directory where the visualization/registry searches for plugins
# directory where the visualization registry searches for plugins
self.visualization_plugins_directory = kwargs.get(
'visualization_plugins_directory', 'config/plugins/visualizations' )
ie_dirs = kwargs.get( 'interactive_environment_plugins_directory', None )
@@ -470,6 +472,16 @@ class Configuration( object ):
else:
return None
def reload_sanitize_whitelist( self ):
self.sanitize_whitelist = []
try:
with open(self.sanitize_whitelist_file, 'rt') as f:
for line in f.readlines():
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.")
def __parse_config_file_options( self, kwargs ):
"""
Backwards compatibility for config files moved to the config/ dir.
+2 -2
View File
@@ -891,7 +891,7 @@ Binary.register_sniffable_binary_format('sra', 'sra', Sra)
class RData( Binary ):
"""Generic R Data file datatype implementation"""
file_ext = 'rdata'
file_ext = 'RData'
def __init__( self, **kwd ):
Binary.__init__( self, **kwd )
@@ -909,4 +909,4 @@ class RData( Binary ):
except:
return False
Binary.register_sniffable_binary_format('rdata', 'rdata', RData)
Binary.register_sniffable_binary_format('RData', 'RData', RData)
+4
View File
@@ -371,6 +371,10 @@ class Data( object ):
if not preview or isinstance(data.datatype, datatypes.images.Image) or os.stat( data.file_name ).st_size < max_peek_size:
if trans.app.config.sanitize_all_html and trans.response.get_content_type() == "text/html":
# Sanitize anytime we respond with plain text/html content.
# Check to see if this dataset's parent job is whitelisted
# We cannot currently trust imported datasets for rendering.
if not data.creating_job.imported and data.creating_job.tool_id in trans.app.config.sanitize_whitelist:
return open(data.file_name).read()
return sanitize_html(open( data.file_name ).read())
return open( data.file_name )
else:
+7 -5
View File
@@ -12,17 +12,18 @@ ross lazarus for rgenetics
august 20 2007
"""
import logging
import os
import sys
import logging
import data
from cgi import escape
import urllib
from galaxy.web import url_for
from cgi import escape
from galaxy.datatypes import metadata
from galaxy.datatypes.images import Html
from galaxy.datatypes.metadata import MetadataElement
from galaxy.datatypes.tabular import Tabular
from galaxy.datatypes.images import Html
from galaxy.web import url_for
from . import data
gal_Log = logging.getLogger(__name__)
verbose = False
@@ -164,6 +165,7 @@ class GenomeGraphs( Tabular ):
Determines whether the file is in gg format
"""
f = open(filename, 'r')
f.readline() # header
rows = [f.readline().split()[1:] for x in range(3)] # small sample
# headers = get_headers( filename, '\t' )
for row in rows:
+6 -6
View File
@@ -754,7 +754,7 @@ class JobExternalOutputMetadataWrapper( object ):
if dataset_path.real_path == metadata_files.dataset.file_name:
return dataset_path.false_path or dataset_path.real_path
return ""
line = "%s,%s,%s,%s,%s,%s" % (
line = '"%s,%s,%s,%s,%s,%s"' % (
metadata_path_on_compute(metadata_files.filename_in),
metadata_path_on_compute(metadata_files.filename_kwds),
metadata_path_on_compute(metadata_files.filename_out),
@@ -826,16 +826,16 @@ class JobExternalOutputMetadataWrapper( object ):
sa_session.add( metadata_files )
sa_session.flush()
metadata_files_list.append( metadata_files )
args = "%s %s %s %s" % ( datatypes_config,
job_metadata,
" ".join( map( __metadata_files_list_to_cmd_line, metadata_files_list ) ),
max_metadata_value_size)
args = '"%s" "%s" %s %s' % ( datatypes_config,
job_metadata,
" ".join( map( __metadata_files_list_to_cmd_line, metadata_files_list ) ),
max_metadata_value_size)
if include_command:
# return command required to build
fd, fp = tempfile.mkstemp( suffix='.py', dir=tmp_dir, prefix="set_metadata_" )
metadata_script_file = abspath( fp )
os.fdopen( fd, 'w' ).write( 'from galaxy_ext.metadata.set_metadata import set_metadata; set_metadata()' )
return "python %s %s" % ( metadata_path_on_compute(metadata_script_file), args )
return 'python "%s" %s' % ( metadata_path_on_compute(metadata_script_file), args )
else:
# return args to galaxy_ext.metadata.set_metadata required to build
return args
+4 -2
View File
@@ -641,11 +641,13 @@ class Registry( object ):
<requirement type="package">samtools</requirement>
</requirements>
<action module="galaxy.tools.actions.metadata" class="SetMetadataToolAction"/>
<command>python $set_metadata $__SET_EXTERNAL_METADATA_COMMAND_LINE__</command>
<command>python "${set_metadata}" ${__SET_EXTERNAL_METADATA_COMMAND_LINE__}</command>
<inputs>
<param format="data" name="input1" type="data" label="File to set metadata on."/>
<param name="__ORIGINAL_DATASET_STATE__" type="hidden" value=""/>
<param name="__SET_EXTERNAL_METADATA_COMMAND_LINE__" type="hidden" value=""/>
<param name="__SET_EXTERNAL_METADATA_COMMAND_LINE__" type="hidden" value="">
<sanitizer sanitize="False"/>
</param>
</inputs>
<configfiles>
<configfile name="set_metadata">from galaxy_ext.metadata.set_metadata import set_metadata; set_metadata()</configfile>
+4 -6
View File
@@ -1189,9 +1189,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 ( not self.external_output_metadata.external_metadata_set_successfully(
dataset, self.sa_session ) and
self.app.config.retry_metadata_internally ):
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 )
@@ -1199,9 +1198,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 ( not self.external_output_metadata.external_metadata_set_successfully(
dataset, self.sa_session ) and
job.states.ERROR != final_job_state ):
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
+1 -1
View File
@@ -446,7 +446,7 @@ class JobHandlerQueue( object ):
.where(and_(model.Job.table.c.state.in_((model.Job.states.QUEUED,
model.Job.states.RUNNING,
model.Job.states.RESUBMITTED)),
(model.Job.table.c.user_id is not None)))
(model.Job.table.c.user_id != null())))
.group_by(model.Job.table.c.user_id))
for row in query:
self.user_job_count[row[0]] = row[1]
+29 -14
View File
@@ -10,24 +10,39 @@ class AnnotatableManagerMixin( object ):
#: class of AnnotationAssociation (e.g. HistoryAnnotationAssociation)
annotation_assoc = None
# TODO: most of this seems to be covered by item_attrs.UsesAnnotations
# TODO: use these below (serializer/deserializer)
def user_annotation( self, item, user ):
return item.get_item_annotation_str( self.session(), user, item )
def annotation( self, item ):
"""
Return the annotation string made by the `item`'s owner or `None` if there
is no annotation.
"""
# NOTE: only works with sharable (.user)
return self._user_annotation( item, item.user )
def owner_annotation( self, item ):
return self.user_annotation( item, item.user )
def delete_annotation( self, item, user ):
return item.delete_item_annotation( self.session(), user, item )
def annotate( self, item, user, annotation ):
# TODO: should/do we support multiple, non-owner annotation of items?
def annotate( self, item, annotation, user=None, flush=True ):
"""
Create a new annotation on `item` or delete the existing if annotation
is `None`.
"""
if not user:
return None
if annotation is None:
self.delete_annotation( item, user )
self._delete_annotation( item, user, flush=flush )
return None
annotation_obj = item.add_item_annotation( self.session(), user, item, annotation )
return annotation_obj.annotation
if flush:
self.session().flush()
return annotation_obj
def _user_annotation( self, item, user ):
return item.get_item_annotation_str( self.session(), user, item )
def _delete_annotation( self, item, user, flush=True ):
returned = item.delete_item_annotation( self.session(), user, item )
if flush:
self.session().flush()
return returned
class AnnotatableSerializerMixin( object ):
@@ -56,7 +71,7 @@ class AnnotatableDeserializerMixin( object ):
if `val` is None.
"""
val = self.validate.nullable_basestring( key, val )
return self.manager.annotate( item, user, val )
return self.manager.annotate( item, val, user=user, flush=False )
# TODO: I'm not entirely convinced this (or tags) are a good idea for filters since they involve a/the user
+3 -21
View File
@@ -3,10 +3,9 @@ Manager mixins to unify the interface into things that can contain: Datasets
and other (nested) containers.
(e.g. DatasetCollections, Histories, LibraryFolders)
Histories should be DatasetCollections.
Libraries should be DatasetCollections.
"""
# Histories should be DatasetCollections.
# Libraries should be DatasetCollections.
import operator
@@ -28,6 +27,7 @@ class ContainerManagerMixin( object ):
each of the methods below only work on the first level of
nesting.
"""
# TODO: terminology is getting a bit convoluted and silly at this point: rename three public below?
# TODO: this should be an open mapping (not just 2)
#: the classes that can be contained
contained_class = None
@@ -71,24 +71,6 @@ class ContainerManagerMixin( object ):
raise galaxy.exceptions.NotImplemented( 'Abstract class' )
class HistoryAsContainerManagerMixin( ContainerManagerMixin ):
contained_class = model.HistoryDatasetAssociation
subcontainer_class = model.HistoryDatasetCollectionAssociation
order_contents_on = operator.attrgetter( 'hid' )
def _filter_to_contained( self, container, content_class ):
return content_class.history == container
def _content_manager( self, content ):
# type sniffing is inevitable
if isinstance( content, model.HistoryDatasetAssociation ):
return self.hda_manager
elif isinstance( content, model.HistoryDatasetCollectionAssociation ):
return self.hdca_manager
raise TypeError( 'Unknown contents class: ' + str( content ) )
class LibraryFolderAsContainerManagerMixin( ContainerManagerMixin ):
# can contain two types of subcontainer: LibraryFolder, LibraryDatasetCollectionAssociation
# has as the top level container: Library
+10 -3
View File
@@ -196,11 +196,18 @@ class DatasetSerializer( base.ModelSerializer, deletable.PurgableSerializerMixin
return dataset.extra_files_path
self.skip()
def serialize_permissions( self, dataset, key, **context ):
def serialize_permissions( self, dataset, key, user=None, **context ):
"""
"""
permissions = {}
# TODO: use rbac permissions?
if not user or not self.dataset_manager.permissions.manage.is_permitted( dataset, user ):
self.skip()
management_permissions = self.dataset_manager.permissions.manage.by_dataset( dataset )
access_permissions = self.dataset_manager.permissions.access.by_dataset( dataset )
permissions = {
'manage' : [ self.app.security.encode_id( perm.role.id ) for perm in management_permissions ],
'access' : [ self.app.security.encode_id( perm.role.id ) for perm in access_permissions ],
}
return permissions
+13
View File
@@ -120,6 +120,9 @@ class HDAManager( datasets.DatasetAssociationManager,
copy.copied_from_history_dataset_association = hda
copy.set_size()
original_annotation = self.annotation( hda )
self.annotate( copy, original_annotation, user=history.user )
# TODO: update from kwargs?
# Need to set after flushed, as MetadataFiles require dataset.id
@@ -132,6 +135,11 @@ class HDAManager( datasets.DatasetAssociationManager,
copy.set_peek()
self.session().flush()
# these use a second session flush and need to be after the first
original_tags = self.get_tags( hda )
self.set_tags( copy, original_tags, user=history.user )
return copy
def copy_ldda( self, history, ldda, **kwargs ):
@@ -225,6 +233,11 @@ class HDAManager( datasets.DatasetAssociationManager,
hda_data = open( hda.file_name ).read( MAX_PEEK_SIZE )
return truncated, hda_data
# .... annotatable
def annotation( self, hda ):
# override to scope to history owner
return self._user_annotation( hda, hda.history.user )
class HDASerializer( # datasets._UnflattenedMetadataDatasetAssociationSerializer,
datasets.DatasetAssociationSerializer,
+22 -3
View File
@@ -4,10 +4,12 @@ Manager and Serializer for histories.
Histories are containers for datasets or dataset collections
created (or copied) by users over the course of an analysis.
"""
import operator
from galaxy import model
from galaxy.managers import sharable
from galaxy.managers import deletable
from galaxy.managers import containers
from galaxy.managers import hdas
from galaxy.managers import collections_util
@@ -15,7 +17,7 @@ import logging
log = logging.getLogger( __name__ )
class HistoryManager( sharable.SharableModelManager, deletable.PurgableManagerMixin ):
class HistoryManager( sharable.SharableModelManager, deletable.PurgableManagerMixin, containers.ContainerManagerMixin ):
model_class = model.History
foreign_key_name = 'history'
@@ -25,6 +27,10 @@ class HistoryManager( sharable.SharableModelManager, deletable.PurgableManagerMi
annotation_assoc = model.HistoryAnnotationAssociation
rating_assoc = model.HistoryRatingAssociation
contained_class = model.HistoryDatasetAssociation
subcontainer_class = model.HistoryDatasetCollectionAssociation
order_contents_on = operator.attrgetter( 'hid' )
# TODO: incorporate imp/exp (or alias to)
def __init__( self, app, *args, **kwargs ):
@@ -134,8 +140,9 @@ class HistoryManager( sharable.SharableModelManager, deletable.PurgableManagerMi
for content in history.contents_iter( types=[ 'dataset', 'dataset_collection' ] ):
contents_dict = {}
if isinstance( content, model.HistoryDatasetAssociation ):
contents_dict = hda_serializer.serialize_to_view( content, view='detailed',
user=trans.user, trans=trans )
contents_dict = hda_serializer.serialize_to_view(content, view='detailed', user=trans.user, trans=trans )
hda_annotation = hda_serializer.serialize_annotation( content, 'annotation', user=history.user )
contents_dict[ 'annotation' ] = hda_annotation
elif isinstance( content, model.HistoryDatasetCollectionAssociation ):
try:
service = self.app.dataset_collections_service
@@ -164,6 +171,18 @@ class HistoryManager( sharable.SharableModelManager, deletable.PurgableManagerMi
return { 'history': history_dictionary,
'contents': contents_dictionaries }
# container interface
def _filter_to_contained( self, container, content_class ):
return content_class.history == container
def _content_manager( self, content ):
# type sniffing is inevitable
if isinstance( content, model.HistoryDatasetAssociation ):
return self.hda_manager
elif isinstance( content, model.HistoryDatasetCollectionAssociation ):
return self.hdca_manager
raise TypeError( 'Unknown contents class: ' + str( content ) )
class HistorySerializer( sharable.SharableModelSerializer, deletable.PurgableSerializerMixin ):
"""
+3 -3
View File
@@ -256,6 +256,6 @@ class AccessDatasetRBACPermission( DatasetRBACPermission ):
def _role_is_permitted( self, dataset, role ):
current_roles = self._roles( dataset )
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] ) ) )
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] ) ) )
+49 -32
View File
@@ -2,17 +2,61 @@
Mixins for Taggable model managers and serializers.
"""
# from galaxy import exceptions as galaxy_exceptions
import logging
log = logging.getLogger( __name__ )
# TODO: work out the relation between serializers and managers and then fold these into the parent of the two
def _tag_str_gen( item ):
# TODO: which user is this? all?
for tag in item.tags:
tag_str = tag.user_tname
if tag.value is not None:
tag_str += ":" + tag.user_value
yield tag_str
def _tags_to_strings( item ):
if not hasattr( item, 'tags' ):
return None
return list( _tag_str_gen( item ) )
def _tags_from_strings( item, tag_handler, new_tags_list, user=None ):
# TODO: have to assume trans.user here...
if not user:
# raise galaxy_exceptions.RequestParameterMissingException( 'User required for tags on ' + str( item ) )
# TODO: this becomes a 'silent failure' - no tags are set. This is a questionable approach but
# I haven't found a better one for anon users copying items with tags
return
# TODO: duped from tags manager - de-dupe when moved to taggable mixin
tag_handler.delete_item_tags( user, item )
new_tags_str = ','.join( new_tags_list )
tag_handler.apply_item_tags( user, item, unicode( new_tags_str.encode( 'utf-8' ), 'utf-8' ) )
# TODO:!! does the creation of new_tags_list mean there are now more and more unused tag rows in the db?
class TaggableManagerMixin( object ):
#: class of TagAssociation (e.g. HistoryTagAssociation)
tag_assoc = None
# TODO: most of this can be done by delegating to the TagManager?
def get_tags( self, item ):
"""
Return a list of tag strings.
"""
return _tags_to_strings( item )
# def by_user( self, user, **kwargs ):
def set_tags( self, item, new_tags, user=None ):
"""
Set an `item`'s tags from a list of strings.
"""
return _tags_from_strings( item, self.app.tag_handler, new_tags, user=user )
# def tags_by_user( self, user, **kwargs ):
# TODO: here or TagManager
# pass
@@ -25,16 +69,7 @@ class TaggableSerializerMixin( object ):
"""
Return tags as a list of strings.
"""
if not hasattr( item, 'tags' ):
return None
tags_str_list = []
for tag in item.tags:
tag_str = tag.user_tname
if tag.value is not None:
tag_str += ":" + tag.user_value
tags_str_list.append( tag_str )
return tags_str_list
return _tags_to_strings( item )
class TaggableDeserializerMixin( object ):
@@ -49,35 +84,17 @@ class TaggableDeserializerMixin( object ):
Note: this will erase any previous tags.
"""
new_tags_list = self.validate.basestring_list( key, val )
# TODO: have to assume trans.user here...
# TODO: duped from tags manager - de-dupe when moved to taggable mixin
tag_handler = self.app.tag_handler
tag_handler.delete_item_tags( user, item )
new_tags_str = ','.join( new_tags_list )
tag_handler.apply_item_tags( user, item, unicode( new_tags_str.encode( 'utf-8' ), 'utf-8' ) )
# TODO:!! does the creation of new_tags_list mean there are now more and more unused tag rows in the db?
_tags_from_strings( item, self.app.tag_handler, new_tags_list, user=user )
return item.tags
class TaggableFilterMixin( object ):
def _tag_str_gen( self, item ):
"""
Return a list of strings built from the item's tags.
"""
# TODO: which user is this? all?
for tag in item.tags:
tag_str = tag.user_tname
if tag.value is not None:
tag_str += ":" + tag.user_value
yield tag_str
def filter_has_partial_tag( self, item, val ):
"""
Return True if any tag partially contains `val`.
"""
for tag_str in self._tag_str_gen( item ):
for tag_str in _tag_str_gen( item ):
if val in tag_str:
return True
return False
@@ -86,7 +103,7 @@ class TaggableFilterMixin( object ):
"""
Return True if any tag exactly equals `val`.
"""
for tag_str in self._tag_str_gen( item ):
for tag_str in _tag_str_gen( item ):
if val == tag_str:
return True
return False
+2013 -1781
View File
File diff suppressed because it is too large Load Diff
+7 -1
View File
@@ -62,6 +62,11 @@ def reload_display_application(app, **kwargs):
app.datatypes_registry.reload_display_applications( display_application_ids)
def reload_sanitize_whitelist(app):
log.debug("Executing reload sanitize whitelist control task.")
app.config.reload_sanitize_whitelist()
def reload_tool_data_tables(app, **kwargs):
params = util.Params(kwargs)
log.debug("Executing tool data table reload for %s" % params.get('table_names', 'all tables'))
@@ -80,7 +85,8 @@ def admin_job_lock(app, **kwargs):
control_message_to_task = { 'reload_tool': reload_tool,
'reload_display_application': reload_display_application,
'reload_tool_data_tables': reload_tool_data_tables,
'admin_job_lock': admin_job_lock}
'admin_job_lock': admin_job_lock,
'reload_sanitize_whitelist': reload_sanitize_whitelist}
class GalaxyQueueWorker(ConsumerMixin, threading.Thread):
@@ -1180,7 +1180,7 @@ class BBIDataProvider( GenomeDataProvider ):
# Compute $\mu \pm 2\sigma$ to provide an estimate for upper and lower
# bounds that contain ~95% of the data.
mean = summary.sum_data[0] / valid_count
var = summary.sum_squares[0] - mean
var = max( summary.sum_squares[0] - mean, 0 ) # Prevent variance underflow.
if valid_count > 1:
var /= valid_count - 1
sd = math.sqrt( var )
+5 -1
View File
@@ -119,7 +119,6 @@ class VisualizationPlugin( pluginframework.Plugin, ServesStaticPluginMixin, Serv
base_url = context.get( 'base_url', '' )
self.base_url = '/'.join([ base_url, self.name ]) if base_url else self.name
self._set_up_static_plugin()
template_cache_dir = context.get( 'template_cache_dir', None )
@@ -252,6 +251,11 @@ class InteractiveEnvironmentPlugin( VisualizationPlugin ):
"""
INTENV_REQUEST_FACTORY = interactive_environments.InteractiveEnviornmentRequest
def __init__( self, app, path, name, config, context=None, **kwargs ):
# TODO: this is a hack until we can get int envs seperated from the vis reg and into their own framework
context[ 'base_url' ] = 'interactive_environments'
super( InteractiveEnvironmentPlugin, self ).__init__( app, path, name, config, context=context, **kwargs )
def _render( self, render_vars, trans=None, embedded=None, **kwargs ):
"""
Override to add interactive environment specific template vars.
+2 -2
View File
@@ -31,6 +31,7 @@ class VisualizationsRegistry( pluginframework.PageServingPluginManager ):
- validating and parsing params into resources (based on a context)
used in the visualization template
"""
DEFAULT_BASE_URL = 'visualizations'
# these should be handled somewhat differently - and be passed onto their resp. methods in ctrl.visualization
# TODO: change/remove if/when they can be updated to use this system
#: any built in visualizations that have their own render method in ctrls/visualization
@@ -47,8 +48,7 @@ class VisualizationsRegistry( pluginframework.PageServingPluginManager ):
def __init__( self, app, skip_bad_plugins=True, **kwargs ):
self.app = weakref.ref( app )
self.config_parser = config_parser.VisualizationsConfigParser()
super( VisualizationsRegistry, self ).__init__( app, 'visualizations',
skip_bad_plugins=skip_bad_plugins, **kwargs )
super( VisualizationsRegistry, self ).__init__( app, skip_bad_plugins=skip_bad_plugins, **kwargs )
def is_plugin( self, plugin_path ):
"""
+19
View File
@@ -1123,6 +1123,25 @@ class Admin( object ):
job=job,
message="<a href='jobs'>Back</a>" )
@web.expose
@web.require_admin
def sanitize_whitelist( self, trans, submit_whitelist=False, tools_to_whitelist=[]):
if submit_whitelist:
# write the configured sanitize_whitelist_file with new whitelist
# and update in-memory list.
with open(trans.app.config.sanitize_whitelist_file, 'wt') as f:
if isinstance(tools_to_whitelist, basestring):
tools_to_whitelist = [tools_to_whitelist]
new_whitelist = sorted([tid for tid in tools_to_whitelist if tid in trans.app.toolbox.tools_by_id])
f.write("\n".join(new_whitelist))
trans.app.config.sanitize_whitelist = new_whitelist
galaxy.queue_worker.send_control_task(trans.app, 'reload_sanitize_whitelist', noop_self=True)
# dispatch a message to reload list for other processes
return trans.fill_template( '/webapps/galaxy/admin/sanitize_whitelist.mako',
sanitize_all=trans.app.config.sanitize_all_html,
tools=trans.app.toolbox.tools_by_id )
# ---- Utility methods -------------------------------------------------------
@@ -28,7 +28,7 @@ class InteractiveEnviornmentRequest(object):
self.attr.galaxy_config = trans.app.config
self.attr.galaxy_root_dir = os.path.abspath(self.attr.galaxy_config.root)
self.attr.root = web.url_for("/")
self.attr.app_root = self.attr.root + "plugins/visualizations/" + self.attr.viz_id + "/static/"
self.attr.app_root = self.attr.root + "plugins/interactive_environments/" + self.attr.viz_id + "/static/"
plugin_path = os.path.abspath( plugin.path )
+6 -2
View File
@@ -364,6 +364,8 @@ class PageServingPluginManager( PluginManager ):
"""
# TODO: I'm unclear of the utility of this class - it prob. will only have one subclass (vis reg). Fold into?
#: default static url base
DEFAULT_BASE_URL = ''
#: does the class need static files served?
serves_static = True
#: does the class need template files served?
@@ -375,7 +377,7 @@ class PageServingPluginManager( PluginManager ):
#: name of files to search for additional template lookup directories
additional_template_paths_config_filename = 'additional_template_paths.xml'
def __init__( self, app, base_url, template_cache_dir=None, **kwargs ):
def __init__( self, app, base_url='', template_cache_dir=None, **kwargs ):
"""
Set up the manager and load all plugins.
@@ -387,7 +389,9 @@ class PageServingPluginManager( PluginManager ):
:param template_cache_dir: filesytem path to the directory where cached
templates are kept
"""
self.base_url = base_url
self.base_url = base_url or self.DEFAULT_BASE_URL
if not self.base_url:
raise PluginManagerException( 'base_url or DEFAULT_BASE_URL required' )
self.template_cache_dir = template_cache_dir
self.additional_template_paths = []
+1 -1
View File
@@ -353,7 +353,7 @@ class Request( webob.Request ):
@lazy_property
def path( self ):
return self.environ['SCRIPT_NAME'] + self.environ['PATH_INFO']
return self.environ.get('SCRIPT_NAME', '') + self.environ['PATH_INFO']
@lazy_property
def browser_url( self ):
@@ -256,14 +256,16 @@ class HistoryContentsController( BaseAPIController, UsesLibraryMixin, UsesLibrar
original = self.hda_manager.get_accessible( unencoded_hda_id, trans.user )
# check for access on history that contains the original hda as well
self.history_manager.error_unless_accessible( original.history, trans.user, current_history=trans.history )
data_copy = original.copy( copy_children=True )
hda = history.add_dataset( data_copy )
hda = self.hda_manager.copy( original, history=history )
# data_copy = original.copy( copy_children=True )
# hda = history.add_dataset( data_copy )
trans.sa_session.flush()
if not hda:
return None
return self.hda_serializer.serialize_to_view( hda,
user=trans.user, trans=trans, **self._parse_serialization_params( kwd, 'detailed' ) )
user=trans.user, trans=trans, **self._parse_serialization_params( kwd, 'detailed' ) )
def __create_datasets_from_library_folder( self, trans, history, payload, **kwd ):
rval = []
@@ -228,94 +228,104 @@ class AdminToolshed( AdminGalaxy ):
but we may choose to do so in the future if it becomes necessary.
"""
message = escape( kwd.get( 'message', '' ) )
statuses = [ None, '' 'info', 'done', 'warning', 'error' ]
status = kwd.get( 'status', 'done' )
if status in statuses:
status = statuses.index( status )
else:
status = 1
remove_from_disk = kwd.get( 'remove_from_disk', '' )
remove_from_disk_checked = CheckboxField.is_checked( remove_from_disk )
tool_shed_repository = repository_util.get_installed_tool_shed_repository( trans.app, kwd[ 'id' ] )
shed_tool_conf, tool_path, relative_install_dir = \
suc.get_tool_panel_config_tool_path_install_dir( trans.app, tool_shed_repository )
if relative_install_dir:
if tool_path:
relative_install_dir = os.path.join( tool_path, relative_install_dir )
repository_install_dir = os.path.abspath( relative_install_dir )
else:
repository_install_dir = None
errors = ''
if kwd.get( 'deactivate_or_uninstall_repository_button', False ):
if tool_shed_repository.includes_tools_for_display_in_tool_panel:
# Handle tool panel alterations.
tpm = tool_panel_manager.ToolPanelManager( trans.app )
tpm.remove_repository_contents( tool_shed_repository,
shed_tool_conf,
uninstall=remove_from_disk_checked )
if tool_shed_repository.includes_data_managers:
dmh = data_manager.DataManagerHandler( trans.app )
dmh.remove_from_data_manager( tool_shed_repository )
if tool_shed_repository.includes_datatypes:
# Deactivate proprietary datatypes.
cdl = custom_datatype_manager.CustomDatatypeLoader( trans.app )
installed_repository_dict = cdl.load_installed_datatypes( tool_shed_repository,
repository_install_dir,
deactivate=True )
if installed_repository_dict:
converter_path = installed_repository_dict.get( 'converter_path' )
if converter_path is not None:
cdl.load_installed_datatype_converters( installed_repository_dict, deactivate=True )
display_path = installed_repository_dict.get( 'display_path' )
if display_path is not None:
cdl.load_installed_display_applications( installed_repository_dict, deactivate=True )
if remove_from_disk_checked:
try:
# Remove the repository from disk.
shutil.rmtree( repository_install_dir )
log.debug( "Removed repository installation directory: %s" % str( repository_install_dir ) )
removed = True
except Exception, e:
log.debug( "Error removing repository installation directory %s: %s" % ( str( repository_install_dir ), str( e ) ) )
if isinstance( e, OSError ) and not os.path.exists( repository_install_dir ):
tool_shed_repositories = repository_util.get_installed_tool_shed_repository( trans.app, kwd[ 'id' ] )
if not isinstance( tool_shed_repositories, list ):
tool_shed_repositories = [tool_shed_repositories]
for tool_shed_repository in tool_shed_repositories:
shed_tool_conf, tool_path, relative_install_dir = \
suc.get_tool_panel_config_tool_path_install_dir( trans.app, tool_shed_repository )
if relative_install_dir:
if tool_path:
relative_install_dir = os.path.join( tool_path, relative_install_dir )
repository_install_dir = os.path.abspath( relative_install_dir )
else:
repository_install_dir = None
errors = ''
if kwd.get( 'deactivate_or_uninstall_repository_button', False ):
if tool_shed_repository.includes_tools_for_display_in_tool_panel:
# Handle tool panel alterations.
tpm = tool_panel_manager.ToolPanelManager( trans.app )
tpm.remove_repository_contents( tool_shed_repository,
shed_tool_conf,
uninstall=remove_from_disk_checked )
if tool_shed_repository.includes_data_managers:
dmh = data_manager.DataManagerHandler( trans.app )
dmh.remove_from_data_manager( tool_shed_repository )
if tool_shed_repository.includes_datatypes:
# Deactivate proprietary datatypes.
cdl = custom_datatype_manager.CustomDatatypeLoader( trans.app )
installed_repository_dict = cdl.load_installed_datatypes( tool_shed_repository,
repository_install_dir,
deactivate=True )
if installed_repository_dict:
converter_path = installed_repository_dict.get( 'converter_path' )
if converter_path is not None:
cdl.load_installed_datatype_converters( installed_repository_dict, deactivate=True )
display_path = installed_repository_dict.get( 'display_path' )
if display_path is not None:
cdl.load_installed_display_applications( installed_repository_dict, deactivate=True )
if remove_from_disk_checked:
try:
# Remove the repository from disk.
shutil.rmtree( repository_install_dir )
log.debug( "Removed repository installation directory: %s" % str( repository_install_dir ) )
removed = True
log.debug( "Repository directory does not exist on disk, marking as uninstalled." )
else:
removed = False
if removed:
tool_shed_repository.uninstalled = True
# Remove all installed tool dependencies and tool dependencies stuck in the INSTALLING state, but don't touch any
# repository dependencies.
tool_dependencies_to_uninstall = tool_shed_repository.tool_dependencies_installed_or_in_error
tool_dependencies_to_uninstall.extend( tool_shed_repository.tool_dependencies_being_installed )
for tool_dependency in tool_dependencies_to_uninstall:
uninstalled, error_message = tool_dependency_util.remove_tool_dependency( trans.app, tool_dependency )
if error_message:
errors = '%s %s' % ( errors, error_message )
tool_shed_repository.deleted = True
if remove_from_disk_checked:
tool_shed_repository.status = trans.install_model.ToolShedRepository.installation_status.UNINSTALLED
tool_shed_repository.error_message = None
if trans.app.config.manage_dependency_relationships:
# Remove the uninstalled repository and any tool dependencies from the in-memory dictionaries in the
# installed_repository_manager.
trans.app.installed_repository_manager.handle_repository_uninstall( tool_shed_repository )
else:
tool_shed_repository.status = trans.install_model.ToolShedRepository.installation_status.DEACTIVATED
trans.install_model.context.add( tool_shed_repository )
trans.install_model.context.flush()
if remove_from_disk_checked:
message = 'The repository named <b>%s</b> has been uninstalled. ' % escape( tool_shed_repository.name )
if errors:
message += 'Attempting to uninstall tool dependencies resulted in errors: %s' % errors
status = 'error'
except Exception, e:
log.debug( "Error removing repository installation directory %s: %s" % ( str( repository_install_dir ), str( e ) ) )
if isinstance( e, OSError ) and not os.path.exists( repository_install_dir ):
removed = True
log.debug( "Repository directory does not exist on disk, marking as uninstalled." )
else:
removed = False
if removed:
tool_shed_repository.uninstalled = True
# Remove all installed tool dependencies and tool dependencies stuck in the INSTALLING state, but don't touch any
# repository dependencies.
tool_dependencies_to_uninstall = tool_shed_repository.tool_dependencies_installed_or_in_error
tool_dependencies_to_uninstall.extend( tool_shed_repository.tool_dependencies_being_installed )
for tool_dependency in tool_dependencies_to_uninstall:
uninstalled, error_message = tool_dependency_util.remove_tool_dependency( trans.app, tool_dependency )
if error_message:
errors = '%s %s' % ( errors, error_message )
tool_shed_repository.deleted = True
if remove_from_disk_checked:
tool_shed_repository.status = trans.install_model.ToolShedRepository.installation_status.UNINSTALLED
tool_shed_repository.error_message = None
if trans.app.config.manage_dependency_relationships:
# Remove the uninstalled repository and any tool dependencies from the in-memory dictionaries in the
# installed_repository_manager.
trans.app.installed_repository_manager.handle_repository_uninstall( tool_shed_repository )
else:
status = 'done'
else:
message = 'The repository named <b>%s</b> has been deactivated. ' % escape( tool_shed_repository.name )
status = 'done'
tool_shed_repository.status = trans.install_model.ToolShedRepository.installation_status.DEACTIVATED
trans.install_model.context.add( tool_shed_repository )
trans.install_model.context.flush()
if remove_from_disk_checked:
message += 'The repository named <b>%s</b> has been uninstalled. ' % escape( tool_shed_repository.name )
if errors:
message += 'Attempting to uninstall tool dependencies resulted in errors: %s' % errors
status = max( status, statuses.index( 'error' ) )
else:
status = max( status, statuses.index( 'done' ) )
else:
message = 'The repository named <b>%s</b> has been deactivated. ' % escape( tool_shed_repository.name )
status = max( status, statuses.index( 'done' ) )
status = statuses[ status ]
if kwd.get( 'deactivate_or_uninstall_repository_button', False ):
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
action='browse_repositories',
message=message,
status=status ) )
remove_from_disk_check_box = CheckboxField( 'remove_from_disk', checked=remove_from_disk_checked )
return trans.fill_template( '/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako',
repository=tool_shed_repository,
repository=tool_shed_repositories,
remove_from_disk_check_box=remove_from_disk_check_box,
message=message,
status=status )
@@ -60,13 +60,17 @@ class CloudController(BaseUIController):
"""
Get EC2 Account Info
"""
account_info = {}
cml = cloudman.launch.CloudManLauncher(key_id, secret)
ec2_conn = cml.connect_ec2(key_id, secret)
kps = ec2_conn.get_all_key_pairs()
account_info['clusters'] = cml.get_clusters_pd()
account_info['keypairs'] = [akp.name for akp in kps]
return dumps(account_info)
try:
account_info = {}
cml = cloudman.launch.CloudManLauncher(key_id, secret)
ec2_conn = cml.connect_ec2(key_id, secret)
kps = ec2_conn.get_all_key_pairs()
account_info['clusters'] = cml.get_clusters_pd()
account_info['keypairs'] = [akp.name for akp in kps]
return dumps(account_info)
except EC2ResponseError as e:
trans.response.status = 400
return e.message
@web.expose
def launch_instance(self, trans, cluster_name, password, key_id, secret,
@@ -569,7 +569,7 @@ class HistoryController( BaseUIController, SharableMixin, UsesAnnotations, UsesI
hda_dictionaries = history_data[ 'contents' ]
jobs = ( trans.sa_session.query( trans.app.model.Job )
.filter( trans.app.model.Job.user == trans.user )
.filter( trans.app.model.Job.user == history_to_view.user )
.filter( trans.app.model.Job.history_id == unencoded_history_id ) ).all()
jobs = map( lambda j: self.encode_all_ids( trans, j.to_dict( 'element' ), True ), jobs )
@@ -15,7 +15,7 @@ from galaxy import eggs
eggs.require( "MarkupSafe" )
from markupsafe import escape
eggs.require('sqlalchemy')
from sqlalchemy import and_, or_
from sqlalchemy import and_, or_, true
from galaxy import model
from galaxy import util
@@ -33,6 +33,7 @@ from galaxy.web.base.controller import (BaseUIController,
UsesFormDefinitionsMixin)
from galaxy.web.form_builder import build_select_field, CheckboxField
from galaxy.web.framework.helpers import grids, time_ago
from galaxy.exceptions import ObjectInvalid
log = logging.getLogger( __name__ )
@@ -1153,7 +1154,7 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat
# Invalidate all other sessions
for other_galaxy_session in trans.sa_session.query( trans.app.model.GalaxySession ) \
.filter( and_( trans.app.model.GalaxySession.table.c.user_id == user.id,
trans.app.model.GalaxySession.table.c.is_valid is True,
trans.app.model.GalaxySession.table.c.is_valid == true(),
trans.app.model.GalaxySession.table.c.id != trans.galaxy_session.id ) ):
other_galaxy_session.is_valid = False
trans.sa_session.add( other_galaxy_session )
@@ -1697,6 +1698,10 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat
new_len.visible = False
new_len.state = trans.app.model.Job.states.OK
new_len.info = "custom build .len file"
try:
trans.app.object_store.create( new_len.dataset )
except ObjectInvalid:
raise Exception( 'Unable to create output dataset: object store is full' )
trans.sa_session.flush()
counter = 0
f = open(new_len.file_name, "w")
@@ -1649,16 +1649,16 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
# Return only metadata revisions where tools_functionally_correct is set to True.
metadata_filter = and_( trans.model.RepositoryMetadata.table.c.includes_tools == true(),
trans.model.RepositoryMetadata.table.c.tools_functionally_correct == true(),
trans.model.RepositoryMetadata.table.c.time_last_tested is not None )
trans.model.RepositoryMetadata.table.c.time_last_tested != null() )
elif status == 'failed':
# Return only metadata revisions where tools_functionally_correct is set to False.
metadata_filter = and_( trans.model.RepositoryMetadata.table.c.includes_tools == true(),
trans.model.RepositoryMetadata.table.c.tools_functionally_correct == false(),
trans.model.RepositoryMetadata.table.c.time_last_tested is not None )
trans.model.RepositoryMetadata.table.c.time_last_tested != null() )
else:
# Return all metadata entries for this user's repositories.
metadata_filter = and_( trans.model.RepositoryMetadata.table.c.includes_tools == true(),
trans.model.RepositoryMetadata.table.c.time_last_tested is not None )
trans.model.RepositoryMetadata.table.c.time_last_tested != null() )
tool_shed_url = web.url_for( '/', qualified=True )
functional_test_results = []
@@ -196,7 +196,7 @@ class InstalledRepositoryGrid( grids.Grid ):
condition=( lambda item:
not item.deleted and
item.status != tool_shed_install.ToolShedRepository.installation_status.NEW ),
allow_multiple=False,
allow_multiple=True,
url_args=dict( controller='admin_toolshed',
action='browse_repositories',
operation='deactivate or uninstall' ) ),
+11 -2
View File
@@ -275,8 +275,17 @@ def create_repository_admin_role( app, repository ):
def get_installed_tool_shed_repository( app, id ):
"""Get a tool shed repository record from the Galaxy database defined by the id."""
return app.install_model.context.query( app.install_model.ToolShedRepository ) \
.get( app.security.decode_id( id ) )
rval = []
if isinstance( id, list ):
return_list = True
else:
id = [ id ]
return_list = False
for i in id:
rval.append( app.install_model.context.query( app.install_model.ToolShedRepository ).get( app.security.decode_id( i ) ) )
if return_list:
return rval
return rval[0]
def get_repo_info_dict( app, user, repository_id, changeset_revision ):
+2 -1
View File
@@ -1,4 +1,5 @@
from markupsafe import escape as raw_escape
from galaxy.util import smart_str
ALLOWED_ELEMENTS = ["<b>", "</b>", "<br/>"]
ALLOWED_MAP = dict(map(lambda x: (x, raw_escape(x)), ALLOWED_ELEMENTS))
@@ -14,7 +15,7 @@ def escape( string ):
>>> escape("A <b>repo</b>")
u'A <b>repo</b>'
"""
escaped = str( raw_escape( string ) )
escaped = smart_str( raw_escape( string ), encoding="ascii", errors="replace" )
# Unescape few selected tags.
for key, value in ALLOWED_MAP.iteritems():
escaped = escaped.replace(value, key)
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"ui-slider.js","sources":["../../../src/mvc/ui/ui-slider.js"],"names":["define","Utils","View","Backbone","extend","optionsDefault","id","uid","min","max","step","precise","split","initialize","options","self","this","merge","setElement","_template","useslider","$slider","$el","find","slider","on","event","ui","value","css","$text","undefined","$","val","pressed","e","which","onchange","v","indexOf","preventDefault","new_val","isNaN","Math"],"mappings":"AACAA,QAAQ,eAAgB,SAASC,GAGjC,GAAIC,GAAOC,SAASD,KAAKE,QAErBC,gBACIC,GAAUL,EAAMM,MAChBC,IAAU,KACVC,IAAU,KACVC,KAAU,KACVC,SAAU,EACVC,MAAU,KAIdC,WAAa,SAASC,GAElB,GAAIC,GAAOC,IAGXA,MAAKF,QAAUb,EAAMgB,MAAMH,EAASE,KAAKX,gBAGzCW,KAAKE,WAAWF,KAAKG,UAAUH,KAAKF,UAGpCE,KAAKI,UAAiC,OAArBJ,KAAKF,QAAQL,KAAqC,OAArBO,KAAKF,QAAQN,KAAgBQ,KAAKF,QAAQL,IAAMO,KAAKF,QAAQN,IAGjF,OAAtBQ,KAAKF,QAAQJ,OACbM,KAAKF,QAAQJ,KAAO,EAChBM,KAAKF,QAAQH,SAAWK,KAAKI,YAC7BJ,KAAKF,QAAQJ,MAAQM,KAAKF,QAAQL,IAAMO,KAAKF,QAAQN,KAAOQ,KAAKF,QAAQF,QAK7EI,KAAKI,WACLJ,KAAKK,QAAUL,KAAKM,IAAIC,KAAK,WAC7BP,KAAKK,QAAQG,OAAOR,KAAKF,SACzBE,KAAKK,QAAQI,GAAG,QAAS,SAAUC,EAAOC,GACtCZ,EAAKa,MAAMD,EAAGC,UAGlBZ,KAAKM,IAAIC,KAAK,wBAAwBM,IAAI,QAAS,QAIvDb,KAAKc,MAAQd,KAAKM,IAAIC,KAAK,SAGAQ,SAAvBf,KAAKF,QAAQc,OACbZ,KAAKY,MAAMZ,KAAKF,QAAQc,OAI5BZ,KAAKc,MAAML,GAAG,SAAU,WACpBV,EAAKa,MAAMI,EAAEhB,MAAMiB,QAIvB,IAAIC,KACJlB,MAAKc,MAAML,GAAG,QAAS,SAASU,GAC5BD,EAAQC,EAAEC,QAAS,EACnBrB,EAAKD,QAAQuB,UAAYtB,EAAKD,QAAQuB,SAASL,EAAEhB,MAAMiB,SAE3DjB,KAAKc,MAAML,GAAG,UAAW,SAAUU,GAC/B,GAAIG,GAAIH,EAAEC,KACVF,GAAQI,IAAK,EACF,GAALA,GAAe,GAALA,GAAe,IAALA,GAAgB,IAALA,GAAgB,IAALA,GAAYA,GAAK,IAAW,IAALA,GAC1D,KAALA,GAA0C,IAA9BN,EAAEhB,MAAMiB,MAAMM,QAAQ,MAAcxB,EAAKD,QAAQH,SACxD,KAAL2B,GAA0C,IAA9BN,EAAEhB,MAAMiB,MAAMM,QAAQ,MACnCL,EAAQ,KAAOA,EAAQ,KAC1BR,MAAMc,oBAMlBZ,MAAQ,SAAUa,GA0Bd,MAzBgBV,UAAZU,IACgB,OAAZA,GAAgC,KAAZA,IAEhBC,MAAMD,KACNA,EAAU,GAIW,OAArBzB,KAAKF,QAAQL,MACbgC,EAAUE,KAAKnC,IAAIiC,EAASzB,KAAKF,QAAQL,MAEpB,OAArBO,KAAKF,QAAQN,MACbiC,EAAUE,KAAKlC,IAAIgC,EAASzB,KAAKF,QAAQN,OAKjDQ,KAAKK,SAAWL,KAAKK,QAAQG,OAAO,QAASiB,GAC7CzB,KAAKc,MAAMG,IAAIQ,GAGfzB,KAAKF,QAAQuB,UAAYrB,KAAKF,QAAQuB,SAASI,IAI5CzB,KAAKc,MAAMG,OAItBd,UAAW,SAASL,GAChB,MAAQ,YAAcA,EAAQR,GAAK,+IAO3C,QACIJ,KAAOA"}
{"version":3,"file":"ui-slider.js","sources":["../../../src/mvc/ui/ui-slider.js"],"names":["define","Utils","View","Backbone","extend","optionsDefault","id","uid","min","max","step","precise","split","initialize","options","self","this","merge","setElement","_template","useslider","$slider","$el","find","slider","on","event","ui","value","css","$text","undefined","$","val","pressed","e","which","onchange","v","indexOf","preventDefault","new_val","isNaN","Math"],"mappings":"AACAA,QAAQ,eAAgB,SAASC,GAGjC,GAAIC,GAAOC,SAASD,KAAKE,QAErBC,gBACIC,GAAUL,EAAMM,MAChBC,IAAU,KACVC,IAAU,KACVC,KAAU,KACVC,SAAU,EACVC,MAAU,KAIdC,WAAa,SAASC,GAElB,GAAIC,GAAOC,IAGXA,MAAKF,QAAUb,EAAMgB,MAAMH,EAASE,KAAKX,gBAGzCW,KAAKE,WAAWF,KAAKG,UAAUH,KAAKF,UAGpCE,KAAKI,UAAiC,OAArBJ,KAAKF,QAAQL,KAAqC,OAArBO,KAAKF,QAAQN,KAAgBQ,KAAKF,QAAQL,IAAMO,KAAKF,QAAQN,IAGjF,OAAtBQ,KAAKF,QAAQJ,OACbM,KAAKF,QAAQJ,KAAO,EAChBM,KAAKF,QAAQH,SAAWK,KAAKI,YAC7BJ,KAAKF,QAAQJ,MAAQM,KAAKF,QAAQL,IAAMO,KAAKF,QAAQN,KAAOQ,KAAKF,QAAQF,QAK7EI,KAAKI,WACLJ,KAAKK,QAAUL,KAAKM,IAAIC,KAAK,WAC7BP,KAAKK,QAAQG,OAAOR,KAAKF,SACzBE,KAAKK,QAAQI,GAAG,QAAS,SAAUC,EAAOC,GACtCZ,EAAKa,MAAMD,EAAGC,UAGlBZ,KAAKM,IAAIC,KAAK,wBAAwBM,IAAI,QAAS,QAIvDb,KAAKc,MAAQd,KAAKM,IAAIC,KAAK,SAGAQ,SAAvBf,KAAKF,QAAQc,OACbZ,KAAKY,MAAMZ,KAAKF,QAAQc,OAI5BZ,KAAKc,MAAML,GAAG,SAAU,WACpBV,EAAKa,MAAMI,EAAEhB,MAAMiB,QAIvB,IAAIC,KACJlB,MAAKc,MAAML,GAAG,QAAS,SAASU,GAC5BD,EAAQC,EAAEC,QAAS,EACnBrB,EAAKD,QAAQuB,UAAYtB,EAAKD,QAAQuB,SAASL,EAAEhB,MAAMiB,SAE3DjB,KAAKc,MAAML,GAAG,UAAW,SAAUU,GAC/B,GAAIG,GAAIH,EAAEC,KACVF,GAAQI,IAAK,EACF,GAALA,GAAe,GAALA,GAAe,IAALA,GAAgB,IAALA,GAAgB,IAALA,GAAYA,GAAK,IAAW,IAALA,GAAaA,GAAK,IAAW,KAALA,IACjF,KAALA,GAAiB,KAALA,IAA2C,IAA9BN,EAAEhB,MAAMiB,MAAMM,QAAQ,MAAcxB,EAAKD,QAAQH,UACrE,KAAL2B,GAAiB,KAALA,IAA2C,IAA9BN,EAAEhB,MAAMiB,MAAMM,QAAQ,MACjDL,EAAQ,KAAOA,EAAQ,KAC1BR,MAAMc,oBAMlBZ,MAAQ,SAAUa,GA0Bd,MAzBgBV,UAAZU,IACgB,OAAZA,GAAgC,KAAZA,IAEhBC,MAAMD,KACNA,EAAU,GAIW,OAArBzB,KAAKF,QAAQL,MACbgC,EAAUE,KAAKnC,IAAIiC,EAASzB,KAAKF,QAAQL,MAEpB,OAArBO,KAAKF,QAAQN,MACbiC,EAAUE,KAAKlC,IAAIgC,EAASzB,KAAKF,QAAQN,OAKjDQ,KAAKK,SAAWL,KAAKK,QAAQG,OAAO,QAASiB,GAC7CzB,KAAKc,MAAMG,IAAIQ,GAGfzB,KAAKF,QAAQuB,UAAYrB,KAAKF,QAAQuB,SAASI,IAI5CzB,KAAKc,MAAMG,OAItBd,UAAW,SAASL,GAChB,MAAQ,YAAcA,EAAQR,GAAK,+IAO3C,QACIJ,KAAOA"}
@@ -1 +1 @@
{"version":3,"file":"panel_section.js","sources":["../../../src/templates/compiled/panel_section.js"],"names":["template","Handlebars","templates","compiler","main","depth0","helpers","partials","data","helper","alias1","helperMissing","alias2","alias3","this","escapeExpression","id","call","name","hash","useData"],"mappings":"CAAA,WACE,GAAIA,GAAWC,WAAWD,SAAUE,EAAYD,WAAWC,UAAYD,WAAWC,aACpFA,GAAyB,cAAIF,GAAUG,UAAY,EAAE,mBAAmBC,KAAO,SAASC,EAAOC,EAAQC,EAASC,GAC5G,GAAIC,GAAQC,EAAOJ,EAAQK,cAAeC,EAAO,WAAYC,EAAOC,KAAKC,gBAE3E,OAAO,2CACHF,GAASJ,EAA2E,OAAjEA,EAASH,EAAQU,KAAiB,MAAVX,EAAiBA,EAAOW,GAAKX,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKZ,GAAQa,KAAO,KAAKC,QAAUX,KAAOA,IAASC,IAClM,8CACAI,GAASJ,EAA+E,OAArEA,EAASH,EAAQY,OAAmB,MAAVb,EAAiBA,EAAOa,KAAOb,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKZ,GAAQa,KAAO,OAAOC,QAAUX,KAAOA,IAASC,IACxM,iCACAI,GAASJ,EAA2E,OAAjEA,EAASH,EAAQU,KAAiB,MAAVX,EAAiBA,EAAOW,GAAKX,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKZ,GAAQa,KAAO,KAAKC,QAAUX,KAAOA,IAASC,IAClM,oGACJW,SAAU"}
{"version":3,"file":"panel_section.js","sources":["../../../src/templates/compiled/panel_section.js"],"names":["this","Handlebars","template","compiler","main","depth0","helpers","partials","data","helper","alias1","helperMissing","alias2","alias3","escapeExpression","id","call","name","hash","useData"],"mappings":"AAAAA,KAAiB,WAAIA,KAAiB,eACtCA,KAAiB,WAAa,UAAIA,KAAiB,WAAa,cAEhEA,KAAiB,WAAa,UAAiB,cAAIC,WAAWC,UAAUC,UAAY,EAAE,mBAAmBC,KAAO,SAASC,EAAOC,EAAQC,EAASC,GAC7I,GAAIC,GAAQC,EAAOJ,EAAQK,cAAeC,EAAO,WAAYC,EAAOb,KAAKc,gBAE3E,OAAO,2CACHD,GAASJ,EAA2E,OAAjEA,EAASH,EAAQS,KAAiB,MAAVV,EAAiBA,EAAOU,GAAKV,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKX,GAAQY,KAAO,KAAKC,QAAUV,KAAOA,IAASC,IAClM,8CACAI,GAASJ,EAA+E,OAArEA,EAASH,EAAQW,OAAmB,MAAVZ,EAAiBA,EAAOY,KAAOZ,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKX,GAAQY,KAAO,OAAOC,QAAUV,KAAOA,IAASC,IACxM,iCACAI,GAASJ,EAA2E,OAAjEA,EAASH,EAAQS,KAAiB,MAAVV,EAAiBA,EAAOU,GAAKV,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKX,GAAQY,KAAO,KAAKC,QAAUV,KAAOA,IAASC,IAClM,oGACJU,SAAU"}
@@ -1 +1 @@
{"version":3,"file":"tool_form.js","sources":["../../../src/templates/compiled/tool_form.js"],"names":["template","Handlebars","templates","1","depth0","helpers","partials","data","stack1","helper","alias1","helperMissing","alias2","alias3","this","escapeExpression","name","call","hash","label","html","help","compiler","main","version","each","inputs","fn","program","inverse","noop","useData"],"mappings":"CAAA,WACE,GAAIA,GAAWC,WAAWD,SAAUE,EAAYD,WAAWC,UAAYD,WAAWC,aACpFA,GAAqB,UAAIF,GAAUG,EAAI,SAASC,EAAOC,EAAQC,EAASC,GACpE,GAAIC,GAAQC,EAAQC,EAAOL,EAAQM,cAAeC,EAAO,WAAYC,EAAOC,KAAKC,gBAEnF,OAAO,2DACHF,GAASJ,EAA+E,OAArEA,EAASJ,EAAQW,OAAmB,MAAVZ,EAAiBA,EAAOY,KAAOZ,IAAmBK,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKb,GAAQY,KAAO,OAAOE,QAAUX,KAAOA,IAASE,IACxM,KACAI,GAASJ,EAAiF,OAAvEA,EAASJ,EAAQc,QAAoB,MAAVf,EAAiBA,EAAOe,MAAQf,IAAmBK,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKb,GAAQY,KAAO,QAAQE,QAAUX,KAAOA,IAASE,IAC3M,yEACyN,OAA5MA,EAA+E,OAArEA,EAASJ,EAAQe,OAAmB,MAAVhB,EAAiBA,EAAOgB,KAAOhB,IAAmBK,EAASC,EAA1GF,QAA0HC,KAAWG,EAASH,EAAOQ,KAAKb,GAAQY,KAAO,OAAOE,QAAUX,KAAOA,IAASE,GAAoBD,EAAS,IACzO,uGACAK,GAASJ,EAA+E,OAArEA,EAASJ,EAAQgB,OAAmB,MAAVjB,EAAiBA,EAAOiB,KAAOjB,IAAmBK,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKb,GAAQY,KAAO,OAAOE,QAAUX,KAAOA,IAASE,IACxM,wFACJa,UAAY,EAAE,mBAAmBC,KAAO,SAASnB,EAAOC,EAAQC,EAASC,GACvE,GAAIC,GAAQC,EAAQC,EAAOL,EAAQM,cAAeC,EAAO,WAAYC,EAAOC,KAAKC,gBAEnF,OAAO,8BACHF,GAASJ,EAA+E,OAArEA,EAASJ,EAAQW,OAAmB,MAAVZ,EAAiBA,EAAOY,KAAOZ,IAAmBK,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKb,GAAQY,KAAO,OAAOE,QAAUX,KAAOA,IAASE,IACxM,aACAI,GAASJ,EAAqF,OAA3EA,EAASJ,EAAQmB,UAAsB,MAAVpB,EAAiBA,EAAOoB,QAAUpB,IAAmBK,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKb,GAAQY,KAAO,UAAUE,QAAUX,KAAOA,IAASE,IACjN,6CAC2K,OAAzKD,EAASH,EAAQoB,KAAKR,KAAKb,EAAkB,MAAVA,EAAiBA,EAAOsB,OAAStB,GAASY,KAAO,OAAOE,QAAUS,GAAKb,KAAKc,QAAQ,EAAGrB,EAAM,GAAGsB,QAAUf,KAAKgB,KAAKvB,KAAOA,KAAkBC,EAAS,IAC3L,4MACAK,GAASJ,EAA+E,OAArEA,EAASJ,EAAQgB,OAAmB,MAAVjB,EAAiBA,EAAOiB,KAAOjB,IAAmBK,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKb,GAAQY,KAAO,OAAOE,QAAUX,KAAOA,IAASE,IACxM,kBACJsB,SAAU"}
{"version":3,"file":"tool_form.js","sources":["../../../src/templates/compiled/tool_form.js"],"names":["this","Handlebars","template","1","depth0","helpers","partials","data","stack1","helper","alias1","helperMissing","alias2","alias3","escapeExpression","name","call","hash","label","html","help","compiler","main","version","each","inputs","fn","program","inverse","noop","useData"],"mappings":"AAAAA,KAAiB,WAAIA,KAAiB,eACtCA,KAAiB,WAAa,UAAIA,KAAiB,WAAa,cAEhEA,KAAiB,WAAa,UAAa,UAAIC,WAAWC,UAAUC,EAAI,SAASC,EAAOC,EAAQC,EAASC,GACrG,GAAIC,GAAQC,EAAQC,EAAOL,EAAQM,cAAeC,EAAO,WAAYC,EAAOb,KAAKc,gBAEnF,OAAO,2DACHD,GAASJ,EAA+E,OAArEA,EAASJ,EAAQU,OAAmB,MAAVX,EAAiBA,EAAOW,KAAOX,IAAmBK,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKZ,GAAQW,KAAO,OAAOE,QAAUV,KAAOA,IAASE,IACxM,KACAI,GAASJ,EAAiF,OAAvEA,EAASJ,EAAQa,QAAoB,MAAVd,EAAiBA,EAAOc,MAAQd,IAAmBK,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKZ,GAAQW,KAAO,QAAQE,QAAUV,KAAOA,IAASE,IAC3M,yEACyN,OAA5MA,EAA+E,OAArEA,EAASJ,EAAQc,OAAmB,MAAVf,EAAiBA,EAAOe,KAAOf,IAAmBK,EAASC,EAA1GF,QAA0HC,KAAWG,EAASH,EAAOO,KAAKZ,GAAQW,KAAO,OAAOE,QAAUV,KAAOA,IAASE,GAAoBD,EAAS,IACzO,uGACAK,GAASJ,EAA+E,OAArEA,EAASJ,EAAQe,OAAmB,MAAVhB,EAAiBA,EAAOgB,KAAOhB,IAAmBK,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKZ,GAAQW,KAAO,OAAOE,QAAUV,KAAOA,IAASE,IACxM,wFACJY,UAAY,EAAE,mBAAmBC,KAAO,SAASlB,EAAOC,EAAQC,EAASC,GACvE,GAAIC,GAAQC,EAAQC,EAAOL,EAAQM,cAAeC,EAAO,WAAYC,EAAOb,KAAKc,gBAEnF,OAAO,8BACHD,GAASJ,EAA+E,OAArEA,EAASJ,EAAQU,OAAmB,MAAVX,EAAiBA,EAAOW,KAAOX,IAAmBK,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKZ,GAAQW,KAAO,OAAOE,QAAUV,KAAOA,IAASE,IACxM,aACAI,GAASJ,EAAqF,OAA3EA,EAASJ,EAAQkB,UAAsB,MAAVnB,EAAiBA,EAAOmB,QAAUnB,IAAmBK,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKZ,GAAQW,KAAO,UAAUE,QAAUV,KAAOA,IAASE,IACjN,6CAC2K,OAAzKD,EAASH,EAAQmB,KAAKR,KAAKZ,EAAkB,MAAVA,EAAiBA,EAAOqB,OAASrB,GAASW,KAAO,OAAOE,QAAUS,GAAK1B,KAAK2B,QAAQ,EAAGpB,EAAM,GAAGqB,QAAU5B,KAAK6B,KAAKtB,KAAOA,KAAkBC,EAAS,IAC3L,4MACAK,GAASJ,EAA+E,OAArEA,EAASJ,EAAQe,OAAmB,MAAVhB,EAAiBA,EAAOgB,KAAOhB,IAAmBK,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKZ,GAAQW,KAAO,OAAOE,QAAUV,KAAOA,IAASE,IACxM,kBACJqB,SAAU"}
@@ -1 +1 @@
{"version":3,"file":"tool_link.js","sources":["../../../src/templates/compiled/tool_link.js"],"names":["template","Handlebars","templates","compiler","main","depth0","helpers","partials","data","helper","alias1","helperMissing","alias2","alias3","this","escapeExpression","id","call","name","hash","link","target","min_width","description","useData"],"mappings":"CAAA,WACE,GAAIA,GAAWC,WAAWD,SAAUE,EAAYD,WAAWC,UAAYD,WAAWC,aACpFA,GAAqB,UAAIF,GAAUG,UAAY,EAAE,mBAAmBC,KAAO,SAASC,EAAOC,EAAQC,EAASC,GACxG,GAAIC,GAAQC,EAAOJ,EAAQK,cAAeC,EAAO,WAAYC,EAAOC,KAAKC,gBAE3E,OAAO,aACHF,GAASJ,EAA2E,OAAjEA,EAASH,EAAQU,KAAiB,MAAVX,EAAiBA,EAAOW,GAAKX,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKZ,GAAQa,KAAO,KAAKC,QAAUX,KAAOA,IAASC,IAClM,qBACAI,GAASJ,EAA+E,OAArEA,EAASH,EAAQc,OAAmB,MAAVf,EAAiBA,EAAOe,KAAOf,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKZ,GAAQa,KAAO,OAAOC,QAAUX,KAAOA,IAASC,IACxM,aACAI,GAASJ,EAAmF,OAAzEA,EAASH,EAAQe,SAAqB,MAAVhB,EAAiBA,EAAOgB,OAAShB,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKZ,GAAQa,KAAO,SAASC,QAAUX,KAAOA,IAASC,IAC9M,kBACAI,GAASJ,EAAyF,OAA/EA,EAASH,EAAQgB,YAAwB,MAAVjB,EAAiBA,EAAOiB,UAAYjB,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKZ,GAAQa,KAAO,YAAYC,QAAUX,KAAOA,IAASC,IACvN,KACAI,GAASJ,EAA+E,OAArEA,EAASH,EAAQY,OAAmB,MAAVb,EAAiBA,EAAOa,KAAOb,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKZ,GAAQa,KAAO,OAAOC,QAAUX,KAAOA,IAASC,IACxM,QACAI,GAASJ,EAA6F,OAAnFA,EAASH,EAAQiB,cAA0B,MAAVlB,EAAiBA,EAAOkB,YAAclB,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKZ,GAAQa,KAAO,cAAcC,QAAUX,KAAOA,IAASC,KACjOe,SAAU"}
{"version":3,"file":"tool_link.js","sources":["../../../src/templates/compiled/tool_link.js"],"names":["this","Handlebars","template","compiler","main","depth0","helpers","partials","data","helper","alias1","helperMissing","alias2","alias3","escapeExpression","id","call","name","hash","link","target","min_width","description","useData"],"mappings":"AAAAA,KAAiB,WAAIA,KAAiB,eACtCA,KAAiB,WAAa,UAAIA,KAAiB,WAAa,cAEhEA,KAAiB,WAAa,UAAa,UAAIC,WAAWC,UAAUC,UAAY,EAAE,mBAAmBC,KAAO,SAASC,EAAOC,EAAQC,EAASC,GACzI,GAAIC,GAAQC,EAAOJ,EAAQK,cAAeC,EAAO,WAAYC,EAAOb,KAAKc,gBAE3E,OAAO,aACHD,GAASJ,EAA2E,OAAjEA,EAASH,EAAQS,KAAiB,MAAVV,EAAiBA,EAAOU,GAAKV,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKX,GAAQY,KAAO,KAAKC,QAAUV,KAAOA,IAASC,IAClM,qBACAI,GAASJ,EAA+E,OAArEA,EAASH,EAAQa,OAAmB,MAAVd,EAAiBA,EAAOc,KAAOd,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKX,GAAQY,KAAO,OAAOC,QAAUV,KAAOA,IAASC,IACxM,aACAI,GAASJ,EAAmF,OAAzEA,EAASH,EAAQc,SAAqB,MAAVf,EAAiBA,EAAOe,OAASf,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKX,GAAQY,KAAO,SAASC,QAAUV,KAAOA,IAASC,IAC9M,kBACAI,GAASJ,EAAyF,OAA/EA,EAASH,EAAQe,YAAwB,MAAVhB,EAAiBA,EAAOgB,UAAYhB,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKX,GAAQY,KAAO,YAAYC,QAAUV,KAAOA,IAASC,IACvN,KACAI,GAASJ,EAA+E,OAArEA,EAASH,EAAQW,OAAmB,MAAVZ,EAAiBA,EAAOY,KAAOZ,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKX,GAAQY,KAAO,OAAOC,QAAUV,KAAOA,IAASC,IACxM,QACAI,GAASJ,EAA6F,OAAnFA,EAASH,EAAQgB,cAA0B,MAAVjB,EAAiBA,EAAOiB,YAAcjB,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKX,GAAQY,KAAO,cAAcC,QAAUV,KAAOA,IAASC,KACjOc,SAAU"}
@@ -1 +1 @@
{"version":3,"file":"tool_search.js","sources":["../../../src/templates/compiled/tool_search.js"],"names":["template","Handlebars","templates","compiler","main","depth0","helpers","partials","data","helper","alias1","helperMissing","alias2","alias3","this","escapeExpression","search_hint_string","call","name","hash","spinner_url","useData"],"mappings":"CAAA,WACE,GAAIA,GAAWC,WAAWD,SAAUE,EAAYD,WAAWC,UAAYD,WAAWC,aACpFA,GAAuB,YAAIF,GAAUG,UAAY,EAAE,mBAAmBC,KAAO,SAASC,EAAOC,EAAQC,EAASC,GAC1G,GAAIC,GAAQC,EAAOJ,EAAQK,cAAeC,EAAO,WAAYC,EAAOC,KAAKC,gBAE3E,OAAO,gDACHF,GAASJ,EAA2G,OAAjGA,EAASH,EAAQU,qBAAiC,MAAVX,EAAiBA,EAAOW,mBAAqBX,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKZ,GAAQa,KAAO,qBAAqBC,QAAUX,KAAOA,IAASC,IAClP,0JACAI,GAASJ,EAA6F,OAAnFA,EAASH,EAAQc,cAA0B,MAAVf,EAAiBA,EAAOe,YAAcf,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOQ,KAAKZ,GAAQa,KAAO,cAAcC,QAAUX,KAAOA,IAASC,IAC7N,oDACJY,SAAU"}
{"version":3,"file":"tool_search.js","sources":["../../../src/templates/compiled/tool_search.js"],"names":["this","Handlebars","template","compiler","main","depth0","helpers","partials","data","helper","alias1","helperMissing","alias2","alias3","escapeExpression","search_hint_string","call","name","hash","spinner_url","useData"],"mappings":"AAAAA,KAAiB,WAAIA,KAAiB,eACtCA,KAAiB,WAAa,UAAIA,KAAiB,WAAa,cAEhEA,KAAiB,WAAa,UAAe,YAAIC,WAAWC,UAAUC,UAAY,EAAE,mBAAmBC,KAAO,SAASC,EAAOC,EAAQC,EAASC,GAC3I,GAAIC,GAAQC,EAAOJ,EAAQK,cAAeC,EAAO,WAAYC,EAAOb,KAAKc,gBAE3E,OAAO,gDACHD,GAASJ,EAA2G,OAAjGA,EAASH,EAAQS,qBAAiC,MAAVV,EAAiBA,EAAOU,mBAAqBV,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKX,GAAQY,KAAO,qBAAqBC,QAAUV,KAAOA,IAASC,IAClP,0JACAI,GAASJ,EAA6F,OAAnFA,EAASH,EAAQa,cAA0B,MAAVd,EAAiBA,EAAOc,YAAcd,IAAmBI,EAASC,QAAgBD,KAAWG,EAASH,EAAOO,KAAKX,GAAQY,KAAO,cAAcC,QAAUV,KAAOA,IAASC,IAC7N,oDACJW,SAAU"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,2 +1,2 @@
define(["utils/utils"],function(a){var b=Backbone.View.extend({optionsDefault:{id:a.uid(),min:null,max:null,step:null,precise:!1,split:1e4},initialize:function(b){var c=this;this.options=a.merge(b,this.optionsDefault),this.setElement(this._template(this.options)),this.useslider=null!==this.options.max&&null!==this.options.min&&this.options.max>this.options.min,null===this.options.step&&(this.options.step=1,this.options.precise&&this.useslider&&(this.options.step=(this.options.max-this.options.min)/this.options.split)),this.useslider?(this.$slider=this.$el.find("#slider"),this.$slider.slider(this.options),this.$slider.on("slide",function(a,b){c.value(b.value)})):this.$el.find(".ui-form-slider-text").css("width","100%"),this.$text=this.$el.find("#text"),void 0!==this.options.value&&this.value(this.options.value),this.$text.on("change",function(){c.value($(this).val())});var d=[];this.$text.on("keyup",function(a){d[a.which]=!1,c.options.onchange&&c.options.onchange($(this).val())}),this.$text.on("keydown",function(a){var b=a.which;d[b]=!0,8==b||9==b||13==b||37==b||39==b||b>=48&&57>=b||190==b&&-1==$(this).val().indexOf(".")&&c.options.precise||189==b&&-1==$(this).val().indexOf("-")||d[91]||d[17]||event.preventDefault()})},value:function(a){return void 0!==a&&(null!==a&&""!==a&&(isNaN(a)&&(a=0),null!==this.options.max&&(a=Math.min(a,this.options.max)),null!==this.options.min&&(a=Math.max(a,this.options.min))),this.$slider&&this.$slider.slider("value",a),this.$text.val(a),this.options.onchange&&this.options.onchange(a)),this.$text.val()},_template:function(a){return'<div id="'+a.id+'" class="ui-form-slider"><input id="text" type="text" class="ui-form-slider-text"/><div id="slider" class="ui-form-slider-element"/></div>'}});return{View:b}});
define(["utils/utils"],function(a){var b=Backbone.View.extend({optionsDefault:{id:a.uid(),min:null,max:null,step:null,precise:!1,split:1e4},initialize:function(b){var c=this;this.options=a.merge(b,this.optionsDefault),this.setElement(this._template(this.options)),this.useslider=null!==this.options.max&&null!==this.options.min&&this.options.max>this.options.min,null===this.options.step&&(this.options.step=1,this.options.precise&&this.useslider&&(this.options.step=(this.options.max-this.options.min)/this.options.split)),this.useslider?(this.$slider=this.$el.find("#slider"),this.$slider.slider(this.options),this.$slider.on("slide",function(a,b){c.value(b.value)})):this.$el.find(".ui-form-slider-text").css("width","100%"),this.$text=this.$el.find("#text"),void 0!==this.options.value&&this.value(this.options.value),this.$text.on("change",function(){c.value($(this).val())});var d=[];this.$text.on("keyup",function(a){d[a.which]=!1,c.options.onchange&&c.options.onchange($(this).val())}),this.$text.on("keydown",function(a){var b=a.which;d[b]=!0,8==b||9==b||13==b||37==b||39==b||b>=48&&57>=b||b>=96&&105>=b||(190==b||110==b)&&-1==$(this).val().indexOf(".")&&c.options.precise||(189==b||109==b)&&-1==$(this).val().indexOf("-")||d[91]||d[17]||event.preventDefault()})},value:function(a){return void 0!==a&&(null!==a&&""!==a&&(isNaN(a)&&(a=0),null!==this.options.max&&(a=Math.min(a,this.options.max)),null!==this.options.min&&(a=Math.max(a,this.options.min))),this.$slider&&this.$slider.slider("value",a),this.$text.val(a),this.options.onchange&&this.options.onchange(a)),this.$text.val()},_template:function(a){return'<div id="'+a.id+'" class="ui-form-slider"><input id="text" type="text" class="ui-form-slider-text"/><div id="slider" class="ui-form-slider-element"/></div>'}});return{View:b}});
//# sourceMappingURL=../../../maps/mvc/ui/ui-slider.js.map
@@ -1,238 +0,0 @@
#!/usr/bin/env python
# Script requires handlebars compiler be installed; use node package manager
# to install handlebars.
"""%prog [options] [ specific .handlebars or .html template file to compile ]
Compiles handlebars templates into javascript for better load times and performance.
Handlebars compilation errors will print to stderr.
NOTE!: you will need node.js, npm, and handlebars (installed from npm) in order to compile templates
See http://handlebarsjs.com/precompilation.html for more info.
Should be called from the $GLX_ROOT/static/scripts/templates directory.
Compiled templates will be written to the compiled/ directory.
If the --multi-ext option is passed a file extension string, the script will:
* search for *.<extension> in the current directory,
* extract each '<script type="text/template"> from the file and write them into a new handlebars file
named using the id of the script tag (eg. id="undeleteMsg" -> undeleteMsg.handlebars)
* these new handlebars scripts will be compiled along with any other handlebars templates in the dir
additionally for each of those files, the script will:
* extract each '<script type="text/javascript"> from the file and write them ALL into a single js file
named using the prefix 'helpers-' and the basename of the enclosing file
(eg. common-templates.html -> helpers-common-templates.js )
* these new handlebars scripts will be compiled along with any other handlebars templates in the dir
These files can be included as if they were templates (eg. h.templates( 'helpers-common-templates' ) )
This hopefully will allow both multiple templates and their associated Handlebars helper functions to be
included in one file.
Currently, this works (best?) if:
* the multiple templates are within one html file
* each template is enclosed in a <script> tag with type="text/template" and some id attribute
* each helper fn is enclosed in a <script> tag with type="text/javascript" and some id attribute
e.g. <script type="text/template" id="history-deletedMsg" class="template">Deleted {{ msg }}</script>
"""
# ------------------------------------------------------------------------------
TODO = """
remove intermediate, handlebars step of multi->handlebars->compiled/.js (if handlebars does stdin)
"""
import sys
from glob import glob
from subprocess import call
import os
from optparse import OptionParser
import re
import logging as log
log.basicConfig(
# level=log.DEBUG,
name=__name__
)
COMPILED_DIR = 'compiled'
COMPILED_EXT = '.js'
COMPILE_CMD_STR = "handlebars %s -f %s"
COMPILE_MINIMIZE_SWITCH = ' -m'
TEMPLATE_TAG = 'script'
TEMPLATE_TYPE = 'text/template'
HELPER_TYPE = 'text/javascript'
# both of these are off by default for backward compat
DEFAULT_MINIMIZATION = False
DEFAULT_MULTI_EXT = None # '.html'
# ------------------------------------------------------------------------------
def parse_html_tag_attrs( string ):
attrs = {}
for match in re.finditer( r'(?P<key>\w+?)=[\'|\"](?P<val>.*?)[\'|\"]', string, re.DOTALL | re.MULTILINE ):
match = match.groupdict()
key = match[ 'key' ]
val = match[ 'val' ]
attrs[ key ] = val
return attrs
def split_on_html_tag( string, tag ):
tag_pattern = r'<%s\s*(?P<attrs>.*?)>(?P<body>.*?)</%s>' % ( tag, tag )
log.debug( tag_pattern )
tag_pattern = re.compile( tag_pattern, re.MULTILINE | re.DOTALL )
found_list = re.findall( tag_pattern, string )
for attrs, body in found_list:
yield ( parse_html_tag_attrs( attrs ), body )
def filter_on_tag_type( generator, type_attr_to_match ):
for attrs, body in generator:
log.debug( 'attrs: %s', str( attrs ) )
if( ( 'type' in attrs )
and ( attrs[ 'type' ] == type_attr_to_match ) ):
yield attrs, body
# ------------------------------------------------------------------------------
def break_multi_template( multi_template_filename ):
"""parse the multi template, writing each template into a new handlebars tmpl and returning their names"""
template_filenames = []
# parse the multi template
print "\nBreaking multi-template file %s into individual templates and helpers:" % ( multi_template_filename )
with open( multi_template_filename, 'r' ) as multi_template_file:
multi_template_file_text = multi_template_file.read()
# write a template file for each template (name based on id in tag)
tag_generator = split_on_html_tag( multi_template_file_text, TEMPLATE_TAG )
for attrs, template_text in filter_on_tag_type( tag_generator, TEMPLATE_TYPE ):
if( 'id' not in attrs ):
log.warning( 'Template has no "id". attrs: %s' % ( str( attrs ) ) )
continue
template_id = attrs[ 'id' ]
template_text = template_text.strip()
handlebar_template_filename = template_id + '.handlebars'
with open( handlebar_template_filename, 'w' ) as handlebar_template_file:
handlebar_template_file.write( template_text )
log.debug( "%s\n%s\n", template_id, template_text )
template_filenames.append( handlebar_template_filename )
# write all helpers to a single 'helper-' prefixed js file in the compilation dir
helper_fns = []
# same tag, different type
tag_generator = split_on_html_tag( multi_template_file_text, TEMPLATE_TAG )
for attrs, helper_text in filter_on_tag_type( tag_generator, HELPER_TYPE ):
helper_text = helper_text.strip()
print '(helper):', ( attrs[ 'id' ] if 'id' in attrs else '(No id)' )
helper_fns.append( helper_text )
if helper_fns:
# prefix original filename (in compiled dir) and write all helper funcs to that file
helper_filename = 'helpers-' + os.path.splitext( multi_template_filename )[0] + '.js'
helper_filename = os.path.join( COMPILED_DIR, helper_filename )
with open( helper_filename, 'w' ) as helper_file:
helper_file.write( '\n'.join( helper_fns ) )
print '(helper functions written to %s)' % helper_filename
print '\n'.join( template_filenames )
return template_filenames
# ------------------------------------------------------------------------------
def compile_template( template_filename, minimize=False ):
"""compile the given template file (optionally minimizing the js) using subprocess.
Use the basename of the template file for the outputed js.
"""
template_basename = os.path.splitext( os.path.split( template_filename )[1] )[0]
compiled_filename = os.path.join( COMPILED_DIR, template_basename + COMPILED_EXT )
command_string = COMPILE_CMD_STR % ( template_filename, compiled_filename )
if minimize:
command_string += COMPILE_MINIMIZE_SWITCH
print command_string
return call( command_string, shell=True )
# ------------------------------------------------------------------------------
def main( options, args ):
"""Break multi template files into single templates, compile all single templates.
If args, compile that as a list of specific handlebars and/or multi template files.
"""
print "(Call this script with the '-h' option for more help)"
handlebars_templates = []
# If specific scripts specified on command line, just compile them,
if len( args ) >= 1:
handlebars_templates = filter( lambda( x ): x.endswith( '.handlebars' ), args )
# otherwise compile all in the current dir
else:
handlebars_templates = glob( '*.handlebars' )
# if desired, break up any passed-in or found multi template files
# adding the names of the new single templates to those needing compilation
multi_template_template_filenames = []
if options.multi_ext:
multi_templates = []
if len( args ) >= 1:
multi_templates = filter( lambda( x ): x.endswith( options.multi_ext ), args )
else:
multi_templates = glob( '*' + options.multi_ext )
for multi_template_filename in multi_templates:
multi_template_template_filenames.extend( break_multi_template( multi_template_filename ) )
# unique filenames only (Q&D)
handlebars_templates = list( set( handlebars_templates + multi_template_template_filenames ) )
# compile the templates
print "\nCompiling templates:"
filenames_w_possible_errors = []
for handlebars_template in handlebars_templates:
shell_ret = compile_template( handlebars_template, options.minimize )
if shell_ret:
filenames_w_possible_errors.append( handlebars_template )
# report any possible errors
if filenames_w_possible_errors:
print "\nThere may have been errors on the following files:"
print ',\n'.join( filenames_w_possible_errors )
print "\nCall this script with the '-h' for more help"
# delete multi template intermediate files
if options.remove_intermediate:
print "\nCleaning up intermediate multi-template template files:"
for filename in multi_template_template_filenames:
try:
print 'removing', filename
os.remove( filename )
except Exception, exc:
print exc
# ------------------------------------------------------------------------------
if __name__ == '__main__':
optparser = OptionParser( usage=__doc__ )
optparser.add_option( '-m', '--minimize', dest='minimize', action='store_true', default=DEFAULT_MINIMIZATION,
help=( 'minimize compiled template scripts via handlebars '
+ '(defaults to %s)' % DEFAULT_MINIMIZATION ) )
optparser.add_option( '--multi-ext', dest='multi_ext', metavar="FILE_EXTENSION", default=DEFAULT_MULTI_EXT,
help=( 'indicates that files ending with the given string contain multiple '
+ 'templates and the script should break those into individual '
+ 'handlebars templates (defaults to "%s")' ) % DEFAULT_MULTI_EXT )
optparser.add_option( '--no-remove', action='store_false', dest='remove_intermediate', default=True,
help=( 'remove intermediate *.handlebars files when using multiple template'
+ 'files (defaults to "True")' ) )
( options, args ) = optparser.parse_args()
sys.exit( main( options, args ) )
@@ -1,2 +1,2 @@
!function(){var a=Handlebars.template,b=Handlebars.templates=Handlebars.templates||{};b.panel_section=a({compiler:[6,">= 2.0.0-beta.1"],main:function(a,b,c,d){var e,f=b.helperMissing,g="function",h=this.escapeExpression;return'<div class="toolSectionTitle" id="title_'+h((e=null!=(e=b.id||(null!=a?a.id:a))?e:f,typeof e===g?e.call(a,{name:"id",hash:{},data:d}):e))+'">\n <a href="javascript:void(0)"><span>'+h((e=null!=(e=b.name||(null!=a?a.name:a))?e:f,typeof e===g?e.call(a,{name:"name",hash:{},data:d}):e))+'</span></a>\n</div>\n<div id="'+h((e=null!=(e=b.id||(null!=a?a.id:a))?e:f,typeof e===g?e.call(a,{name:"id",hash:{},data:d}):e))+'" class="toolSectionBody" style="display: none; ">\n <div class="toolSectionBg"></div>\n<div>'},useData:!0})}();
this.Handlebars=this.Handlebars||{},this.Handlebars.templates=this.Handlebars.templates||{},this.Handlebars.templates.panel_section=Handlebars.template({compiler:[6,">= 2.0.0-beta.1"],main:function(a,b,c,d){var e,f=b.helperMissing,g="function",h=this.escapeExpression;return'<div class="toolSectionTitle" id="title_'+h((e=null!=(e=b.id||(null!=a?a.id:a))?e:f,typeof e===g?e.call(a,{name:"id",hash:{},data:d}):e))+'">\n <a href="javascript:void(0)"><span>'+h((e=null!=(e=b.name||(null!=a?a.name:a))?e:f,typeof e===g?e.call(a,{name:"name",hash:{},data:d}):e))+'</span></a>\n</div>\n<div id="'+h((e=null!=(e=b.id||(null!=a?a.id:a))?e:f,typeof e===g?e.call(a,{name:"id",hash:{},data:d}):e))+'" class="toolSectionBody" style="display: none; ">\n <div class="toolSectionBg"></div>\n<div>'},useData:!0});
//# sourceMappingURL=../../../maps/templates/compiled/panel_section.js.map
@@ -1,2 +1,2 @@
!function(){var a=Handlebars.template,b=Handlebars.templates=Handlebars.templates||{};b.tool_form=a({1:function(a,b,c,d){var e,f,g=b.helperMissing,h="function",i=this.escapeExpression;return' <div class="form-row">\n <label for="'+i((f=null!=(f=b.name||(null!=a?a.name:a))?f:g,typeof f===h?f.call(a,{name:"name",hash:{},data:d}):f))+'">'+i((f=null!=(f=b.label||(null!=a?a.label:a))?f:g,typeof f===h?f.call(a,{name:"label",hash:{},data:d}):f))+':</label>\n <div class="form-row-input">\n '+(null!=(f=null!=(f=b.html||(null!=a?a.html:a))?f:g,e=typeof f===h?f.call(a,{name:"html",hash:{},data:d}):f)?e:"")+'\n </div>\n <div class="toolParamHelp" style="clear: both;">\n '+i((f=null!=(f=b.help||(null!=a?a.help:a))?f:g,typeof f===h?f.call(a,{name:"help",hash:{},data:d}):f))+'\n </div>\n <div style="clear: both;"></div>\n </div>\n'},compiler:[6,">= 2.0.0-beta.1"],main:function(a,b,c,d){var e,f,g=b.helperMissing,h="function",i=this.escapeExpression;return'<div class="toolFormTitle">'+i((f=null!=(f=b.name||(null!=a?a.name:a))?f:g,typeof f===h?f.call(a,{name:"name",hash:{},data:d}):f))+" (version "+i((f=null!=(f=b.version||(null!=a?a.version:a))?f:g,typeof f===h?f.call(a,{name:"version",hash:{},data:d}):f))+')</div>\n <div class="toolFormBody">\n'+(null!=(e=b.each.call(a,null!=a?a.inputs:a,{name:"each",hash:{},fn:this.program(1,d,0),inverse:this.noop,data:d}))?e:"")+' </div>\n <div class="form-row form-actions">\n <input type="submit" class="btn btn-primary" name="runtool_btn" value="Execute">\n</div>\n<div class="toolHelp">\n <div class="toolHelpBody">'+i((f=null!=(f=b.help||(null!=a?a.help:a))?f:g,typeof f===h?f.call(a,{name:"help",hash:{},data:d}):f))+"</div>\n</div>"},useData:!0})}();
this.Handlebars=this.Handlebars||{},this.Handlebars.templates=this.Handlebars.templates||{},this.Handlebars.templates.tool_form=Handlebars.template({1:function(a,b,c,d){var e,f,g=b.helperMissing,h="function",i=this.escapeExpression;return' <div class="form-row">\n <label for="'+i((f=null!=(f=b.name||(null!=a?a.name:a))?f:g,typeof f===h?f.call(a,{name:"name",hash:{},data:d}):f))+'">'+i((f=null!=(f=b.label||(null!=a?a.label:a))?f:g,typeof f===h?f.call(a,{name:"label",hash:{},data:d}):f))+':</label>\n <div class="form-row-input">\n '+(null!=(f=null!=(f=b.html||(null!=a?a.html:a))?f:g,e=typeof f===h?f.call(a,{name:"html",hash:{},data:d}):f)?e:"")+'\n </div>\n <div class="toolParamHelp" style="clear: both;">\n '+i((f=null!=(f=b.help||(null!=a?a.help:a))?f:g,typeof f===h?f.call(a,{name:"help",hash:{},data:d}):f))+'\n </div>\n <div style="clear: both;"></div>\n </div>\n'},compiler:[6,">= 2.0.0-beta.1"],main:function(a,b,c,d){var e,f,g=b.helperMissing,h="function",i=this.escapeExpression;return'<div class="toolFormTitle">'+i((f=null!=(f=b.name||(null!=a?a.name:a))?f:g,typeof f===h?f.call(a,{name:"name",hash:{},data:d}):f))+" (version "+i((f=null!=(f=b.version||(null!=a?a.version:a))?f:g,typeof f===h?f.call(a,{name:"version",hash:{},data:d}):f))+')</div>\n <div class="toolFormBody">\n'+(null!=(e=b.each.call(a,null!=a?a.inputs:a,{name:"each",hash:{},fn:this.program(1,d,0),inverse:this.noop,data:d}))?e:"")+' </div>\n <div class="form-row form-actions">\n <input type="submit" class="btn btn-primary" name="runtool_btn" value="Execute">\n</div>\n<div class="toolHelp">\n <div class="toolHelpBody">'+i((f=null!=(f=b.help||(null!=a?a.help:a))?f:g,typeof f===h?f.call(a,{name:"help",hash:{},data:d}):f))+"</div>\n</div>"},useData:!0});
//# sourceMappingURL=../../../maps/templates/compiled/tool_form.js.map
@@ -1,2 +1,2 @@
!function(){var a=Handlebars.template,b=Handlebars.templates=Handlebars.templates||{};b.tool_link=a({compiler:[6,">= 2.0.0-beta.1"],main:function(a,b,c,d){var e,f=b.helperMissing,g="function",h=this.escapeExpression;return'<a class="'+h((e=null!=(e=b.id||(null!=a?a.id:a))?e:f,typeof e===g?e.call(a,{name:"id",hash:{},data:d}):e))+' tool-link" href="'+h((e=null!=(e=b.link||(null!=a?a.link:a))?e:f,typeof e===g?e.call(a,{name:"link",hash:{},data:d}):e))+'" target="'+h((e=null!=(e=b.target||(null!=a?a.target:a))?e:f,typeof e===g?e.call(a,{name:"target",hash:{},data:d}):e))+'" minsizehint="'+h((e=null!=(e=b.min_width||(null!=a?a.min_width:a))?e:f,typeof e===g?e.call(a,{name:"min_width",hash:{},data:d}):e))+'">'+h((e=null!=(e=b.name||(null!=a?a.name:a))?e:f,typeof e===g?e.call(a,{name:"name",hash:{},data:d}):e))+"</a> "+h((e=null!=(e=b.description||(null!=a?a.description:a))?e:f,typeof e===g?e.call(a,{name:"description",hash:{},data:d}):e))},useData:!0})}();
this.Handlebars=this.Handlebars||{},this.Handlebars.templates=this.Handlebars.templates||{},this.Handlebars.templates.tool_link=Handlebars.template({compiler:[6,">= 2.0.0-beta.1"],main:function(a,b,c,d){var e,f=b.helperMissing,g="function",h=this.escapeExpression;return'<a class="'+h((e=null!=(e=b.id||(null!=a?a.id:a))?e:f,typeof e===g?e.call(a,{name:"id",hash:{},data:d}):e))+' tool-link" href="'+h((e=null!=(e=b.link||(null!=a?a.link:a))?e:f,typeof e===g?e.call(a,{name:"link",hash:{},data:d}):e))+'" target="'+h((e=null!=(e=b.target||(null!=a?a.target:a))?e:f,typeof e===g?e.call(a,{name:"target",hash:{},data:d}):e))+'" minsizehint="'+h((e=null!=(e=b.min_width||(null!=a?a.min_width:a))?e:f,typeof e===g?e.call(a,{name:"min_width",hash:{},data:d}):e))+'">'+h((e=null!=(e=b.name||(null!=a?a.name:a))?e:f,typeof e===g?e.call(a,{name:"name",hash:{},data:d}):e))+"</a> "+h((e=null!=(e=b.description||(null!=a?a.description:a))?e:f,typeof e===g?e.call(a,{name:"description",hash:{},data:d}):e))},useData:!0});
//# sourceMappingURL=../../../maps/templates/compiled/tool_link.js.map
@@ -1,2 +1,2 @@
!function(){var a=Handlebars.template,b=Handlebars.templates=Handlebars.templates||{};b.tool_search=a({compiler:[6,">= 2.0.0-beta.1"],main:function(a,b,c,d){var e,f=b.helperMissing,g="function",h=this.escapeExpression;return'<input type="text" name="query" placeholder="'+h((e=null!=(e=b.search_hint_string||(null!=a?a.search_hint_string:a))?e:f,typeof e===g?e.call(a,{name:"search_hint_string",hash:{},data:d}):e))+'" id="tool-search-query" autocomplete="off" class="search-query parent-width" />\n<a id="search-clear-btn" title="clear search (esc)"> </a>\n<img src="'+h((e=null!=(e=b.spinner_url||(null!=a?a.spinner_url:a))?e:f,typeof e===g?e.call(a,{name:"spinner_url",hash:{},data:d}):e))+'" id="search-spinner" class="search-spinner"/>\n'},useData:!0})}();
this.Handlebars=this.Handlebars||{},this.Handlebars.templates=this.Handlebars.templates||{},this.Handlebars.templates.tool_search=Handlebars.template({compiler:[6,">= 2.0.0-beta.1"],main:function(a,b,c,d){var e,f=b.helperMissing,g="function",h=this.escapeExpression;return'<input type="text" name="query" placeholder="'+h((e=null!=(e=b.search_hint_string||(null!=a?a.search_hint_string:a))?e:f,typeof e===g?e.call(a,{name:"search_hint_string",hash:{},data:d}):e))+'" id="tool-search-query" autocomplete="off" class="search-query parent-width" />\n<a id="search-clear-btn" title="clear search (esc)"> </a>\n<img src="'+h((e=null!=(e=b.spinner_url||(null!=a?a.spinner_url:a))?e:f,typeof e===g?e.call(a,{name:"spinner_url",hash:{},data:d}):e))+'" id="search-spinner" class="search-spinner"/>\n'},useData:!0});
//# sourceMappingURL=../../../maps/templates/compiled/tool_search.js.map
@@ -1,6 +0,0 @@
<div class="toolSectionTitle" id="title_{{id}}">
<a href="javascript:void(0)"><span>{{name}}</span></a>
</div>
<div id="{{id}}" class="toolSectionBody" style="display: none; ">
<div class="toolSectionBg"></div>
<div>
@@ -1,21 +0,0 @@
<div class="toolFormTitle">{{name}} (version {{version}})</div>
<div class="toolFormBody">
{{#each inputs}}
<div class="form-row">
<label for="{{name}}">{{label}}:</label>
<div class="form-row-input">
{{{html}}}
</div>
<div class="toolParamHelp" style="clear: both;">
{{help}}
</div>
<div style="clear: both;"></div>
</div>
{{/each}}
</div>
<div class="form-row form-actions">
<input type="submit" class="btn btn-primary" name="runtool_btn" value="Execute">
</div>
<div class="toolHelp">
<div class="toolHelpBody">{{help}}</div>
</div>
@@ -1 +0,0 @@
<a class="{{id}} tool-link" href="{{link}}" target="{{target}}" minsizehint="{{min_width}}">{{name}}</a> {{description}}
@@ -1,3 +0,0 @@
<input type="text" name="query" placeholder="{{search_hint_string}}" id="tool-search-query" autocomplete="off" class="search-query parent-width" />
<a id="search-clear-btn" title="clear search (esc)"> </a>
<img src="{{spinner_url}}" id="search-spinner" class="search-spinner"/>
File diff suppressed because one or more lines are too long
@@ -3,16 +3,28 @@
<%namespace file="/admin/tool_shed_repository/common.mako" import="*" />
<%namespace file="/admin/tool_shed_repository/repository_actions_menu.mako" import="*" />
${render_galaxy_repository_actions( repository )}
<%
repository = context.get( 'repository', None )
if isinstance( repository, list ):
repositories = repository
else:
repositories = [ repository ]
%>
%if len( repositories ) == 1:
${render_galaxy_repository_actions( repositories[0] )}
%endif
%if message:
${render_msg( message, status )}
%endif
<div class="toolForm">
<form name="deactivate_or_uninstall_repository" id="deactivate_or_uninstall_repository" action="${ h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository' ) }" method="post" >
%for repository in repositories:
<input type="hidden" name="id" value="${ trans.security.encode_id( repository.id ) | h }" />
<div class="toolFormTitle">${repository.name|h}</div>
<div class="toolFormBody">
<form name="deactivate_or_uninstall_repository" id="deactivate_or_uninstall_repository" action="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}" method="post" >
<div class="form-row">
<label>Description:</label>
${repository.description|h}
@@ -169,10 +181,12 @@ ${render_galaxy_repository_actions( repository )}
%endif
%endif
</div>
</div>
%endfor
<div class="form-row">
<%
can_deactivate_repository = repository.can_deactivate
can_uninstall_repository = repository.can_uninstall
can_deactivate_repository = True in map( lambda x: x.can_deactivate, repositories )
can_uninstall_repository = True in map( lambda x: x.can_uninstall, repositories )
%>
%if can_deactivate_repository and can_uninstall_repository:
<% deactivate_uninstall_button_text = "Deactivate or Uninstall" %>
@@ -74,6 +74,7 @@
<div class="toolTitle"><a href="${h.url_for( controller='admin', action='reload_tool' )}" target="galaxy_main">Reload a tool's configuration</a></div>
<div class="toolTitle"><a href="${h.url_for( controller='admin', action='review_tool_migration_stages' )}" target="galaxy_main">Review tool migration stages</a></div>
<div class="toolTitle"><a href="${h.url_for( controller='admin', action='tool_errors' )}" target="galaxy_main">View Tool Error Logs</a></div>
<div class="toolTitle"><a href="${h.url_for( controller='admin', action='sanitize_whitelist' )}" target="galaxy_main">Manage Display Whitelist</a></div>
</div>
</div>
<div class="toolSectionPad"></div>
@@ -0,0 +1,59 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
%if message:
${render_msg( message, status )}
%endif
%if not sanitize_all:
<div><p>You currently have <strong>sanitize_all_html</strong> set to False
in your galaxy configuration file. This prevents Galaxy from sanitizing
tool outputs, which is an important security feature. For improved
security, we recommend you disable the old-style blanket sanitization and
manage it via this whitelist instead.</p></div>
%else:
<div><p>This interface will allow you to mark particular tools as 'trusted'
after which Galaxy will no longer attempt to sanitize any HTML contents of
datasets created by these tools upon display. Please be aware of the
potential security implications of doing this -- bypassing sanitization
using this whitelist disables Galaxy's security feature (for the indicated
tools) that prevents Galaxy from displaying potentially malicious
Javascript.<br/>
Note that datasets originating from an archive import are still sanitized
even when their creating tool is whitelisted since it isn't possible to
validate the information supplied in the archive.</p></div>
<form name="sanitize_whitelist" action="${h.url_for( controller='admin', action='sanitize_whitelist' )}">
<div class="toolForm">
<div class="toolFormTitle">Tool Sanitization Whitelist</div>
<div class="toolFormBody">
<table class="manage-table colored" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<th bgcolor="#D8D8D8">Whitelist</th>
<th bgcolor="#D8D8D8">Name</th>
<th bgcolor="#D8D8D8">ID</th>
</tr>
<% ctr = 0 %>
%for tool in tools.values():
%if ctr % 2 == 1:
<tr class="odd_row">
%else:
<tr class="tr">
%endif
<td>
%if tool.id in trans.app.config.sanitize_whitelist:
<input type="checkbox" name="tools_to_whitelist" value="${tool.id}" checked="checked"/>
%else:
<input type="checkbox" name="tools_to_whitelist" value="${tool.id}"/>
%endif
</td>
<td>${ tool.name | h }</td>
<td>${ tool.id | h }</td>
</tr>
<% ctr += 1 %>
%endfor
</table>
</div>
</div>
<input type="submit" name="submit_whitelist" value="Submit new whitelist"/>
</form>
%endif
@@ -106,9 +106,11 @@ spaceghost.test.begin( 'Test permissions for accessible, published, and inaccess
this.api.assertRaises( function(){
this.api.hdas.index( history.id );
}, 403, 'History is not accessible by user', 'hda index failed with error' );
this.api.assertRaises( function(){
this.api.hdas.show( history.id, hdas[0].id );
}, 403, 'History is not accessible by user', 'hda show failed with error' );
// 150721: accessible hdas in an inaccessible history are considered accessible (since api/datasets does)
// this.api.assertRaises( function(){
// this.api.hdas.show( history.id, hdas[0].id );
// }, 403, 'History is not accessible by user', 'hda show failed with error' );
this.test.assertTrue( utils.isObject( this.api.hdas.show( history.id, hdas[0].id ) ) );
this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
+ ' from an inaccessible history should fail for: ' + history.name );
@@ -155,9 +155,11 @@ spaceghost.test.begin( 'Test permissions for accessible, published, and inaccess
this.api.assertRaises( function(){
this.api.hdas.index( history.id );
}, 403, 'History is not accessible by user', 'hda index failed with error' );
this.api.assertRaises( function(){
this.api.hdas.show( history.id, hdas[0].id );
}, 403, 'History is not accessible by user', 'hda show failed with error' );
// 150721: accessible hdas in an inaccessible history are considered accessible (since api/datasets does)
// this.api.assertRaises( function(){
// this.api.hdas.show( history.id, hdas[0].id );
// }, 403, 'History is not accessible by user', 'hda show failed with error' );
this.test.assertTrue( utils.isObject( this.api.hdas.show( history.id, hdas[0].id ) ) );
this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
+ ' from an inaccessible history should fail for: ' + history.name );
+6 -2
View File
@@ -27,7 +27,7 @@ spaceghost.test.begin( 'Test the form of various HDA states', 0, function suite(
filepathToUpload = '../../test-data/' + filenameToUpload,
uploadId = null,
//TODO: get from the api module - that doesn't exist yet
summaryShouldBeArray = [ '10 lines', 'format', 'txt' ],
summaryShouldBeArray = [ '10 lines' ],
infoShouldBe = 'uploaded txt file',
metadataFiles = null,
peekShouldBeArray = [];
@@ -35,7 +35,11 @@ spaceghost.test.begin( 'Test the form of various HDA states', 0, function suite(
// ------------------------------------------------------------------- set up
// start a new user and upload a file
spaceghost.user.loginOrRegisterUser( email, password );
spaceghost.api.tools.thenUploadToCurrent({ filepath: filepathToUpload }, function upload( id, json ){
spaceghost.api.tools.thenUploadToCurrent({
filepath: filepathToUpload,
ext: 'txt'
}, function upload( id, json ){
uploadId = id;
});
spaceghost.openHomePage();
+4 -3
View File
@@ -129,7 +129,7 @@ HistoryPanel.prototype.waitForHda = function waitForHda( hdaName, then, timeout,
hdaElement = this.elementInfoOrNull( wrapperXpath );
//NOTE: this will probably fail if the name was used on a previous HDA
if( !hdaElement ){ return false; }
var state = hdaElement.attributes[ "class" ].match( /state\-([\w\-_]*)/ )[1];
if( state !== previousState ){
spaceghost.info( 'state: ' + state );
@@ -379,10 +379,11 @@ HistoryPanel.prototype.data = {
title : '.title',
titleButtonArea : '.primary-actions',
summary : '.summary',
blurb : '.blurb .value',
dbkey : '.dbkey .value',
info : '.info',
info : '.info .value',
body : '.details',
primaryActionButtons : '.actions .left',
secondaryActionButtons : '.actions .right',
+15
View File
@@ -120,6 +120,21 @@ class BaseTestCase( test_utils.unittest.TestCase ):
self.assertIsInstance( json.dumps( item ), basestring )
class CreatesCollectionsMixin( object ):
def build_element_identifiers( self, elements ):
identifier_list = []
for element in elements:
src = 'hda'
# if isinstance( element, model.DatasetCollection ):
# src = 'collection'#?
# elif isinstance( element, model.LibraryDatasetDatasetAssociation ):
# src = 'ldda'#?
encoded_id = self.trans.security.encode_id( element.id )
identifier_list.append( dict( src=src, name=element.name, id=encoded_id ) )
return identifier_list
# =============================================================================
if __name__ == '__main__':
# or more generally, nosetests test_resourcemanagers.py -s -v
+2 -13
View File
@@ -11,6 +11,7 @@ test_utils = imp.load_source( 'test_utils',
from galaxy import model
from base import BaseTestCase
from base import CreatesCollectionsMixin
from galaxy.managers.datasets import DatasetManager
from galaxy.managers.histories import HistoryManager
from galaxy.managers.hdas import HDAManager
@@ -25,7 +26,7 @@ user3_data = dict( email='user3@user3.user3', username='user3', password=default
# =============================================================================
class DatasetCollectionManagerTestCase( BaseTestCase ):
class DatasetCollectionManagerTestCase( BaseTestCase, CreatesCollectionsMixin ):
def set_up_managers( self ):
super( DatasetCollectionManagerTestCase, self ).set_up_managers()
@@ -34,18 +35,6 @@ class DatasetCollectionManagerTestCase( BaseTestCase ):
self.history_manager = HistoryManager( self.app )
self.collection_manager = DatasetCollectionManager( self.app )
def build_element_identifiers( self, elements ):
identifier_list = []
for element in elements:
src = 'hda'
# if isinstance( element, model.DatasetCollection ):
# src = 'collection'#?
# elif isinstance( element, model.LibraryDatasetDatasetAssociation ):
# src = 'ldda'#?
encoded_id = self.trans.security.encode_id( element.id )
identifier_list.append( dict( src=src, name=element.name, id=encoded_id ) )
return identifier_list
def test_create_simple_list( self ):
owner = self.user_manager.create( **user2_data )
+6 -4
View File
@@ -112,7 +112,8 @@ class DatasetManagerTestCase( BaseTestCase ):
self.assertTrue( self.dataset_manager.permissions.access.is_permitted( dataset, user3 ) )
def test_create_public_dataset( self ):
self.log( "should be able to create a new Dataset and give it some permissions that actually, you know, might work if there's any justice in this universe" )
self.log( "should be able to create a new Dataset and give it some permissions that actually, you know, "
"might work if there's any justice in this universe" )
owner = self.user_manager.create( **user2_data )
owner_private_role = self.user_manager.private_role( owner )
dataset = self.dataset_manager.create( manage_roles=[ owner_private_role ] )
@@ -134,7 +135,7 @@ class DatasetManagerTestCase( BaseTestCase ):
self.assertTrue( self.dataset_manager.permissions.access.is_permitted( dataset, user3 ) )
def test_create_private_dataset( self ):
self.log( "should be able to create a new Dataset and give it some permissions that actually, you know, might work if there's any justice in this universe" )
self.log( "should be able to create a new Dataset and give it private permissions" )
owner = self.user_manager.create( **user2_data )
owner_private_role = self.user_manager.private_role( owner )
dataset = self.dataset_manager.create(
@@ -216,9 +217,10 @@ class DatasetSerializerTestCase( BaseTestCase ):
self.log( 'should be able to use keys with views' )
serialized = self.dataset_serializer.serialize_to_view( dataset,
view='summary', keys=[ 'permissions' ] )
# file_name is exposed using app.config.expose_dataset_path = True
view='summary', keys=[ 'file_name' ] )
self.assertKeys( serialized,
self.dataset_serializer.views[ 'summary' ] + [ 'permissions' ] )
self.dataset_serializer.views[ 'summary' ] + [ 'file_name' ] )
self.log( 'should be able to use keys on their own' )
serialized = self.dataset_serializer.serialize_to_view( dataset,
+46 -6
View File
@@ -101,6 +101,29 @@ class HDAManagerTestCase( HDATestCase ):
self.assertIsNone( hda3.history, msg="history will be None" )
self.assertEqual( hda3.hid, None, msg="should allow setting hid to None (or any other value)" )
def test_hda_tags( self ):
owner = self.user_manager.create( **user2_data )
history1 = self.history_manager.create( name='history1', user=owner )
dataset1 = self.dataset_manager.create()
hda1 = self.hda_manager.create( history=history1, dataset=dataset1 )
self.log( "should be able to set tags on an hda" )
tags_to_set = [ u'tag-one', u'tag-two' ]
self.hda_manager.set_tags( hda1, tags_to_set, user=owner )
tag_str_array = self.hda_manager.get_tags( hda1 )
self.assertEqual( sorted( tags_to_set ), sorted( tag_str_array ) )
def test_hda_annotation( self ):
owner = self.user_manager.create( **user2_data )
history1 = self.history_manager.create( name='history1', user=owner )
dataset1 = self.dataset_manager.create()
hda1 = self.hda_manager.create( history=history1, dataset=dataset1 )
self.log( "should be able to set annotation on an hda" )
annotation = u'an annotation or анотація'
self.hda_manager.annotate( hda1, annotation, user=owner )
self.assertEqual( self.hda_manager.annotation( hda1 ), annotation )
def test_copy_from_hda( self ):
owner = self.user_manager.create( **user2_data )
history1 = self.history_manager.create( name='history1', user=owner )
@@ -116,6 +139,24 @@ class HDAManagerTestCase( HDATestCase ):
self.assertEqual( hda2.dataset, hda1.dataset )
self.assertNotEqual( hda2, hda1 )
self.log( "tags should be copied between HDAs" )
tagged = self.hda_manager.create( history=history1, dataset=self.dataset_manager.create() )
tags_to_set = [ u'tag-one', u'tag-two' ]
self.hda_manager.set_tags( tagged, tags_to_set, user=owner )
hda2 = self.hda_manager.copy( tagged, history=history1 )
tag_str_array = self.hda_manager.get_tags( hda2 )
self.assertEqual( sorted( tags_to_set ), sorted( tag_str_array ) )
self.log( "annotations should be copied between HDAs" )
annotated = self.hda_manager.create( history=history1, dataset=self.dataset_manager.create() )
annotation = u'( ͡° ͜ʖ ͡°)'
self.hda_manager.annotate( annotated, annotation, user=owner )
hda3 = self.hda_manager.copy( annotated, history=history1 )
hda3_annotation = self.hda_manager.annotation( hda3 )
self.assertEqual( annotation, hda3_annotation )
# def test_copy_from_ldda( self ):
# owner = self.user_manager.create( self.trans, **user2_data )
# history1 = self.history_mgr.create( self.trans, name='history1', user=owner )
@@ -378,7 +419,7 @@ class HDASerializerTestCase( HDATestCase ):
def test_serializers( self ):
hda = self._create_vanilla_hda()
all_keys = list( self.hda_serializer.serializable_keyset )
serialized = self.hda_serializer.serialize( hda, all_keys )
serialized = self.hda_serializer.serialize( hda, all_keys, user=hda.history.user )
self.log( 'everything serialized should be of the proper type' )
# base
@@ -392,7 +433,6 @@ class HDASerializerTestCase( HDATestCase ):
self.assertUUID( serialized[ 'uuid' ] )
self.assertIsInstance( serialized[ 'file_name' ], basestring )
self.assertIsInstance( serialized[ 'extra_files_path' ], basestring )
self.assertIsInstance( serialized[ 'permissions' ], dict )
self.assertIsInstance( serialized[ 'size' ], int )
self.assertIsInstance( serialized[ 'file_size' ], int )
self.assertIsInstance( serialized[ 'nice_size' ], basestring )
@@ -614,11 +654,11 @@ class HDAFilterParserTestCase( HDATestCase ):
# annotatable
self.assertFnFilter( self.filter_parser.parse_filter( 'annotation', 'has', 'wot' ) )
def test_genome_build_filters( self ):
pass
# def test_genome_build_filters( self ):
# pass
def test_data_type_filters( self ):
pass
# def test_data_type_filters( self ):
# pass
# =============================================================================
+66
View File
@@ -4,6 +4,7 @@
import os
import imp
import unittest
import random
test_utils = imp.load_source( 'test_utils',
os.path.join( os.path.dirname( __file__), '../unittest_utils/utility.py' ) )
@@ -18,11 +19,13 @@ from galaxy import model
from galaxy import exceptions
from base import BaseTestCase
from base import CreatesCollectionsMixin
from galaxy.managers.histories import HistoryManager
from galaxy.managers.histories import HistorySerializer
from galaxy.managers.histories import HistoryFilters
from galaxy.managers import hdas
from galaxy.managers import collections
default_password = '123456'
user2_data = dict( email='user2@user2.user2', username='user2', password=default_password )
@@ -725,6 +728,69 @@ class HistoryFiltersTestCase( BaseTestCase ):
self.assertEqual( found, deleted_and_annotated )
# =============================================================================
class HistoryAsContainerTestCase( BaseTestCase, CreatesCollectionsMixin ):
def set_up_managers( self ):
super( HistoryAsContainerTestCase, self ).set_up_managers()
self.history_manager = HistoryManager( self.app )
self.hda_manager = hdas.HDAManager( self.app )
self.collection_manager = collections.DatasetCollectionManager( self.app )
def add_hda_to_history( self, history, **kwargs ):
dataset = self.hda_manager.dataset_manager.create()
hda = self.hda_manager.create( history=history, dataset=dataset, **kwargs )
return hda
def add_list_collection_to_history( self, history, hdas, name='test collection', **kwargs ):
hdca = self.collection_manager.create( self.trans, history, name, 'list',
element_identifiers=self.build_element_identifiers( hdas ) )
return hdca
def test_contents( self ):
user2 = self.user_manager.create( **user2_data )
history = self.history_manager.create( name='history', user=user2 )
self.log( "calling contents on an empty history should return an empty list" )
self.assertEqual( [], list( self.history_manager.contents( history ) ) )
self.log( "calling contents on an history with hdas should return those in order of their hids" )
hdas = [ self.add_hda_to_history( history, name=( 'hda-' + str( x ) ) ) for x in xrange( 3 ) ]
random.shuffle( hdas )
ordered_hda_contents = list( self.history_manager.contents( history ) )
self.assertEqual( map( lambda hda: hda.hid, ordered_hda_contents ), [ 1, 2, 3 ] )
self.log( "calling contents on an history with both hdas and collections should return both" )
hdca = self.add_list_collection_to_history( history, hdas )
all_contents = list( self.history_manager.contents( history ) )
self.assertEqual( all_contents, list( ordered_hda_contents ) + [ hdca ] )
def test_contained( self ):
user2 = self.user_manager.create( **user2_data )
history = self.history_manager.create( name='history', user=user2 )
self.log( "calling contained on an empty history should return an empty list" )
self.assertEqual( [], list( self.history_manager.contained( history ) ) )
self.log( "calling contained on an history with both hdas and collections should return only hdas" )
hdas = [ self.add_hda_to_history( history, name=( 'hda-' + str( x ) ) ) for x in xrange( 3 ) ]
self.add_list_collection_to_history( history, hdas )
self.assertEqual( list( self.history_manager.contained( history ) ), hdas )
def test_subcontainers( self ):
user2 = self.user_manager.create( **user2_data )
history = self.history_manager.create( name='history', user=user2 )
self.log( "calling subcontainers on an empty history should return an empty list" )
self.assertEqual( [], list( self.history_manager.subcontainers( history ) ) )
self.log( "calling subcontainers on an history with both hdas and collections should return only collections" )
hdas = [ self.add_hda_to_history( history, name=( 'hda-' + str( x ) ) ) for x in xrange( 3 ) ]
hdca = self.add_list_collection_to_history( history, hdas )
subcontainers = list( self.history_manager.subcontainers( history ) )
self.assertEqual( subcontainers, [ hdca ] )
# =============================================================================
if __name__ == '__main__':
# or more generally, nosetests test_resourcemanagers.py -s -v