branch merge

This commit is contained in:
Ross Lazarus
2013-10-15 09:38:19 +11:00
10 changed files with 188 additions and 75 deletions
+10 -3
View File
@@ -212,9 +212,16 @@ class DRMAAJobRunner( AsynchronousJobRunner ):
try:
assert external_job_id not in ( None, 'None' ), '(%s/%s) Invalid job id' % ( galaxy_id_tag, external_job_id )
state = self.ds.jobStatus( external_job_id )
# TODO: probably need to keep track of InvalidJobException count and remove after it exceeds some configurable
except ( drmaa.DrmCommunicationException, drmaa.InternalException, drmaa.InvalidJobException ), e:
log.warning( "(%s/%s) job check resulted in %s: %s", galaxy_id_tag, external_job_id, e.__class__.__name__, e )
# InternalException was reported to be necessary on some DRMs, but
# this could cause failures to be detected as completion! Please
# report if you experience problems with this.
except ( drmaa.InvalidJobException, drmaa.InternalException ), e:
# we should only get here if an orphaned job was put into the queue at app startup
log.info( "(%s/%s) job left DRM queue with following message: %s" % ( galaxy_id_tag, external_job_id, e ) )
self.work_queue.put( ( self.finish_job, ajs ) )
continue
except drmaa.DrmCommunicationException, e:
log.warning( "(%s/%s) unable to communicate with DRM: %s" % ( galaxy_id_tag, external_job_id, e ))
new_watched.append( ajs )
continue
except Exception, e:
@@ -9,7 +9,6 @@ import urllib2
import zipfile
import tool_shed.util.shed_util_common as suc
from galaxy.datatypes import checkers
from urllib2 import HTTPError
log = logging.getLogger( __name__ )
+17 -1
View File
@@ -21,6 +21,7 @@ from tool_shed.util import common_util
from tool_shed.util import encoding_util
from tool_shed.util import xml_util
from xml.etree import ElementTree as XmlET
from urllib2 import HTTPError
from galaxy import eggs
eggs.require( 'mercurial' )
@@ -1232,10 +1233,25 @@ def get_tool_shed_status_for_installed_repository( app, repository ):
try:
encoded_tool_shed_status_dict = common_util.tool_shed_get( app, tool_shed_url, url )
tool_shed_status_dict = encoding_util.tool_shed_decode( encoded_tool_shed_status_dict )
return tool_shed_status_dict
except HTTPError, e:
# This should handle backward compatility to the Galaxy 12/20/12 release. We used to only handle updates for an installed revision
# using a boolean value.
log.debug( "Error attempting to get tool shed status for installed repository %s: %s\nAttempting older 'check_for_updates' method.\n" % \
( str( repository.name ), str( e ) ) )
url = url_join( tool_shed_url,
'repository/check_for_updates?name=%s&owner=%s&changeset_revision=%s&from_update_manager=True' % \
( repository.name, repository.owner, repository.changeset_revision ) )
try:
# The value of text will be 'true' or 'false', depending upon whether there is an update available for the installed revision.
text = common_util.tool_shed_get( app, tool_shed_url, url )
return dict( revision_update=text )
except Exception, e:
# The required tool shed may be unavailable, so default the revision_update value to 'false'.
return dict( revision_update='false' )
except Exception, e:
log.exception( "Error attempting to get tool shed status for installed repository %s: %s" % ( str( repository.name ), str( e ) ) )
return {}
return tool_shed_status_dict
def get_updated_changeset_revisions( trans, name, owner, changeset_revision ):
"""
+4
View File
@@ -57,6 +57,10 @@ var GalaxyUpload = Backbone.View.extend(
return;
}
// check if logged in
if (!Galaxy.currUser.get('id'))
return;
// add activate icon
var self = this;
this.button_show = new mod_master.GalaxyMasterIcon (
+43 -59
View File
@@ -24,7 +24,8 @@
error_filesize : "File exceeds 2GB. Please use an FTP client.",
error_default : "Please make sure the file is available.",
error_server : "The server is unavailable.",
error_toomany : "You can only queue <20 files per upload session."
error_toomany : "You can only queue <20 files per upload session.",
error_login : "Uploads require you to log in."
}
// options
@@ -158,6 +159,9 @@
// process an upload, recursive
function process()
{
// log
//console.log("Processing queue..." + queue_length + " (" + queue_running + " / " + queue_pause + ")");
// validate
if (queue_length == 0 || queue_pause)
{
@@ -167,6 +171,9 @@
return;
} else
queue_running = true;
// log
//console.log("Looking for file...");
// get an identifier from the queue
var index = -1;
@@ -181,52 +188,23 @@
// remove from queue
remove(index)
// log
//console.log("Initializing ('" + file.name + "').");
// start
var data = opts.initialize(index, file);
// identify maximum file size
var filesize = file.size;
var maxfilesize = 1048576 * opts.maxfilesize;
// add file to queue
try
// check file size
if (filesize < maxfilesize)
{
// load file read
var reader = new FileReader();
// identify maximum file size
var filesize = file.size;
var maxfilesize = 1048576 * opts.maxfilesize;
// set index
reader.index = index;
if (filesize < maxfilesize)
{
// link load
reader.onload = function(e)
{
send(index, file, data)
};
// link error
reader.onerror = function(e)
{
error(index, file, opts.error_default);
};
// link abort
reader.onabort = function(e)
{
error(index, file, opts.error_default);
};
// read data
reader.readAsDataURL(file);
} else {
// skip file
error(index, file, opts.error_filesize);
}
} catch (err)
{
// parse error
error(index, file, err);
// send data
var data = opts.initialize(index, file);
send(index, file, data)
} else {
// skip file
error(index, file, opts.error_filesize);
}
}
@@ -241,10 +219,17 @@
// prepare request
xhr = new XMLHttpRequest();
xhr.open('POST', opts.url, true);
xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('Cache-Control', 'no-cache');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
// captures state changes
xhr.onreadystatechange = function()
{
// status change
//console.log("Status changed: " + xhr.readyState + ".");
// check for request completed, server connection closed
if (xhr.readyState != xhr.DONE)
return;
@@ -264,14 +249,14 @@
// pass any error to the error option
if (xhr.status < 200 || xhr.status > 299)
{
// format error
// format status
var text = xhr.statusText;
if (!xhr.statusText) {
if (xhr.status == 0)
text = opts.error_server;
else
text = opts.error_default;
}
if (xhr.status == 403)
text = opts.error_login;
else if (xhr.status == 0)
text = opts.error_server;
else if (!text)
text = opts.error_default;
// request error
error(index, file, text + " (" + xhr.status + ")");
@@ -284,13 +269,12 @@
xhr.upload.index = index;
xhr.upload.file = file;
xhr.upload.addEventListener('progress', progress, false);
// open request
xhr.open('POST', opts.url, true);
xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('Cache-Control', 'no-cache');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
// send request
xhr.send(formData);
// sending file
//console.log("Sending file ('" + file.name + "').");
}
// success
@@ -360,7 +344,7 @@
// verify browser compatibility
function compatible()
{
return window.File && window.FileReader && window.FormData && window.XMLHttpRequest && window.FileList;
return window.File && window.FormData && window.XMLHttpRequest && window.FileList;
}
// export functions
+6
View File
@@ -1851,3 +1851,9 @@ div.toolTitleNoSection
.icon-button.chevron-expand {
.sprite(@chevron-expand-bw);
}
// honeypot for registration form
#for_bears {
display: none;
}
+66 -5
View File
@@ -37,25 +37,82 @@
subscribe_check_box = CheckboxField( 'subscribe' )
%>
<script type="text/javascript">
$(document).ready(function() {
function validateString(test_string, type) {
var mail_re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
//var mail_re_RFC822 = /^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*$/;
var username_re = /^[a-z0-9\-]{3,255}$/;
if (type === 'email') {
return mail_re.test(test_string);
} else if (type === 'username'){
return username_re.test(test_string);
}
}
function renderError(message) {
if ($(".errormessage").length === 1) {
$(".errormessage").html(message)
} else {
var div = document.createElement("div");
div.className = "errormessage"
div.innerHTML = message;
document.body.insertBefore(div, document.body.firstChild);
}
}
$('#registration').bind('submit', function(e) {
$('#send').attr('disabled', 'disabled');
// we need this value to detect submitting at backend
var hidden_input = '<input type="hidden" id="create_user_button" name="create_user_button" value="Submit"/>';
$("#email_input").before(hidden_input);
var error_text_email= 'Please enter your valid email address';
var error_text_email_long= 'Email cannot be more than 255 characters in length';
var error_text_username_characters = 'Public name must contain only lowercase letters, numbers and "-". It also has to be shorter than 255 characters but longer than 3.';
var error_text_password_short = 'Please use a password of at least 6 characters';
var error_text_password_match = "Passwords don't match";
var validForm = true;
var email = $('#email_input').val();
var name = $('#name_input').val()
if (email.length > 255){ renderError(error_text_email_long); validForm = false;}
else if (!validateString(email,"email")){ renderError(error_text_email); validForm = false;}
else if (!($('#password_input').val() === $('#password_check_input').val())){ renderError(error_text_password_match); validForm = false;}
else if ($('#password_input').val().length < 6 ){ renderError(error_text_password_short); validForm = false;}
else if (!(validateString(name,"username"))){ renderError(error_text_username_characters); validForm = false;}
if (!validForm) {
e.preventDefault();
// reactivate the button if the form wasn't submitted
$('#send').removeAttr('disabled');
}
});
});
</script>
<div class="toolForm">
<form name="registration" id="registration" action="${form_action}" method="post" >
<div class="toolFormTitle">Create account</div>
<div class="form-row">
<label>Email address:</label>
<input type="text" name="email" value="${email | h}" size="40"/>
<input id="email_input" type="text" name="email" value="${email | h}" size="40"/>
<input type="hidden" name="redirect" value="${redirect | h}" size="40"/>
</div>
<div class="form-row">
<label>Password:</label>
<input type="password" name="password" value="" size="40"/>
<input id="password_input" type="password" name="password" value="" size="40"/>
</div>
<div class="form-row">
<label>Confirm password:</label>
<input type="password" name="confirm" value="" size="40"/>
<input id="password_check_input" type="password" name="confirm" value="" size="40"/>
</div>
<div class="form-row">
<label>Public name:</label>
<input type="text" name="username" size="40" value="${username |h}"/>
<input id="name_input" type="text" name="username" size="40" value="${username |h}"/>
%if t.webapp.name == 'galaxy':
<div class="toolParamHelp" style="clear: both;">
Your public name is an identifier that will be used to generate addresses for information
@@ -103,8 +160,12 @@
<input type="hidden" name="user_type_fd_id" value="${trans.security.encode_id( user_type_form_definition.id )}"/>
%endif
%endif
<div id="for_bears">
If you see this, please leave following field blank.
<input type="text" name="please leave this field blank" size="1" value=""/>
</div>
<div class="form-row">
<input type="submit" name="create_user_button" value="Submit"/>
<input type="submit" id="send" name="create_user_button" value="Submit"/>
</div>
</form>
%if registration_warning_message:
+5 -5
View File
@@ -952,11 +952,11 @@ class TwillTestCase( unittest.TestCase ):
# HACK: don't use panels because late_javascripts() messes up the twill browser and it
# can't find form fields (and hence user can't be logged in).
self.visit_url( "%s/user/create?cntrller=%s&use_panels=False" % ( self.url, cntrller ) )
tc.fv( '1', 'email', email )
tc.fv( '1', 'redirect', redirect )
tc.fv( '1', 'password', password )
tc.fv( '1', 'confirm', password )
tc.fv( '1', 'username', username )
tc.fv( 'registration', 'email', email )
tc.fv( 'registration', 'redirect', redirect )
tc.fv( 'registration', 'password', password )
tc.fv( 'registration', 'confirm', password )
tc.fv( 'registration', 'username', username )
tc.submit( 'create_user_button' )
previously_created = False
username_taken = False
@@ -8,39 +8,59 @@ log = logging.getLogger(__name__)
def delete_obj( obj ):
sa_session.delete( obj )
sa_session.flush()
def delete_user_roles( user ):
for ura in user.roles:
sa_session.delete( ura )
sa_session.flush()
def flush( obj ):
sa_session.add( obj )
sa_session.flush()
def get_repository( repository_id ):
return sa_session.query( model.ToolShedRepository ) \
.filter( model.ToolShedRepository.table.c.id == repository_id ) \
.first()
def get_installed_repository_by_name_owner_changeset_revision( name, owner, changeset_revision ):
return sa_session.query( model.ToolShedRepository ) \
.filter( and_( model.ToolShedRepository.table.c.name == name,
model.ToolShedRepository.table.c.owner == owner,
model.ToolShedRepository.table.c.installed_changeset_revision == changeset_revision ) ) \
.one()
def get_private_role( user ):
for role in user.all_roles():
if role.name == user.email and role.description == 'Private Role for %s' % user.email:
return role
raise AssertionError( "Private role not found for user '%s'" % user.email )
def get_tool_dependencies_for_installed_repository( repository_id, status=None ):
if status is not None:
return sa_session.query( model.ToolDependency ) \
.filter( and_( model.ToolDependency.table.c.tool_shed_repository_id == repository_id,
model.ToolDependency.table.c.status == status ) ) \
.all()
else:
return sa_session.query( model.ToolDependency ) \
.filter( model.ToolDependency.table.c.tool_shed_repository_id == repository_id ) \
.all()
def mark_obj_deleted( obj ):
obj.deleted = True
sa_session.add( obj )
sa_session.flush()
def refresh( obj ):
sa_session.refresh( obj )
def get_private_role( user ):
for role in user.all_roles():
if role.name == user.email and role.description == 'Private Role for %s' % user.email:
return role
raise AssertionError( "Private role not found for user '%s'" % user.email )
def get_user( email ):
return sa_session.query( model.User ) \
.filter( model.User.table.c.email==email ) \
@@ -149,4 +149,20 @@ class InstallTestRepository( TwillTestCase ):
strings_displayed.append( 'has been deactivated' )
else:
strings_displayed.append( 'has been uninstalled' )
self.check_for_strings( strings_displayed, strings_not_displayed=[] )
self.check_for_strings( strings_displayed, strings_not_displayed=[] )
# Get all tool dependencies that are in an error state and uninstall them explicitly, so that the next installation attempt
# may succeed.
error_state = model.ToolDependency.installation_status.ERROR
tool_dependencies = test_db_util.get_tool_dependencies_for_installed_repository( installed_repository.id, status=error_state )
if len( tool_dependencies ) > 0:
encoded_tool_dependency_ids = [ self.security.encode_id( tool_dependency.id ) for tool_dependency in tool_dependencies ]
self.uninstall_tool_dependencies( self.security.encode_id( installed_repository.id ), encoded_tool_dependency_ids )
def uninstall_tool_dependencies( self, encoded_repository_id, encoded_tool_dependency_ids ):
tool_dependency_ids = ','.join( encoded_tool_dependency_ids )
url = '/admin_toolshed/uninstall_tool_dependencies?repository_id=%s&inst_td_ids=%s&operation=uninstall' % \
( encoded_repository_id, tool_dependency_ids )
self.visit_url( url )
tc.fv( 'uninstall_tool_dependencies', 'tool_dependency_ids', tool_dependency_ids )
tc.submit( 'uninstall_tool_dependencies_button' )