mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge branch 'dev' of https://github.com/galaxyproject/galaxy into Reports_newpage
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
.venv/
|
||||
contrib/
|
||||
client/
|
||||
database/
|
||||
doc/patch.py
|
||||
doc/source/conf.py
|
||||
lib/galaxy/model/migrate/versions/
|
||||
@@ -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
@@ -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' ] );
|
||||
};
|
||||
|
||||
@@ -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
@@ -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;
|
||||
},
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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' );
|
||||
};
|
||||
@@ -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",
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 ):
|
||||
"""
|
||||
|
||||
@@ -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] ) ) )
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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 )
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 ):
|
||||
"""
|
||||
|
||||
@@ -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 )
|
||||
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
|
||||
@@ -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' ) ),
|
||||
|
||||
@@ -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 ):
|
||||
|
||||
@@ -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 @@
|
||||
{"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,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 );
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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',
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 )
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user