galaxy-commits
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions
commit/galaxy-central: greg: Dont' assume a complex repository dependency was properly defined.
by Bitbucket 30 Jan '13
by Bitbucket 30 Jan '13
30 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/04e221996871/
changeset: 04e221996871
user: greg
date: 2013-01-30 22:47:20
summary: Dont' assume a complex repository dependency was properly defined.
affected #: 1 file
diff -r ea3da2000fa733a2d3ff5d5629dec58d3573645c -r 04e22199687138a539734d108bc711fe96ab1083 lib/galaxy/util/shed_util_common.py
--- a/lib/galaxy/util/shed_util_common.py
+++ b/lib/galaxy/util/shed_util_common.py
@@ -1223,7 +1223,8 @@
current_rd_tups, error_message = handle_repository_elem( app=app,
repository_elem=sub_elem,
repository_dependencies_tups=None )
- repository_dependency_tup = current_rd_tups[ 0 ]
+ if current_rd_tups:
+ repository_dependency_tup = current_rd_tups[ 0 ]
if requirements_dict:
dependency_key = '%s/%s' % ( package_name, package_version )
tool_dependencies_dict[ dependency_key ] = requirements_dict
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Support for installation and administration of complex repository dependencies in Galaxy.
by Bitbucket 30 Jan '13
by Bitbucket 30 Jan '13
30 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ea3da2000fa7/
changeset: ea3da2000fa7
user: greg
date: 2013-01-30 22:29:37
summary: Support for installation and administration of complex repository dependencies in Galaxy.
affected #: 7 files
diff -r 618c34d9b2eab385e092c9ca2d7dd07b9ea31024 -r ea3da2000fa733a2d3ff5d5629dec58d3573645c lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -3153,6 +3153,11 @@
def can_reinstall_or_activate( self ):
return self.deleted
@property
+ def has_readme_files( self ):
+ if self.metadata:
+ return 'readme_files' in self.metadata
+ return False
+ @property
def has_repository_dependencies( self ):
if self.metadata:
return 'repository_dependencies' in self.metadata
@@ -3176,11 +3181,6 @@
def in_error_state( self ):
return self.status == self.installation_status.ERROR
@property
- def has_readme_files( self ):
- if self.metadata:
- return 'readme_files' in self.metadata
- return False
- @property
def repository_dependencies( self ):
required_repositories = []
for rrda in self.required_repositories:
diff -r 618c34d9b2eab385e092c9ca2d7dd07b9ea31024 -r ea3da2000fa733a2d3ff5d5629dec58d3573645c lib/galaxy/tool_shed/tool_dependencies/fabric_util.py
--- a/lib/galaxy/tool_shed/tool_dependencies/fabric_util.py
+++ b/lib/galaxy/tool_shed/tool_dependencies/fabric_util.py
@@ -50,6 +50,7 @@
install_dir = actions_dict[ 'install_dir' ]
package_name = actions_dict[ 'package_name' ]
actions = actions_dict.get( 'actions', None )
+ filtered_actions = []
if actions:
with make_tmp_dir() as work_dir:
with lcd( work_dir ):
@@ -57,6 +58,8 @@
# are currently only two supported processes; download_by_url and clone via a "shell_command" action type.
action_type, action_dict = actions[ 0 ]
if action_type == 'download_by_url':
+ # Eliminate the download_by_url action so remaining actions can be processed correctly.
+ filtered_actions = actions[ 1: ]
url = action_dict[ 'url' ]
if 'target_filename' in action_dict:
downloaded_filename = action_dict[ 'target_filename' ]
@@ -75,15 +78,24 @@
dir = work_dir
elif action_type == 'shell_command':
# <action type="shell_command">git clone --recursive git://github.com/ekg/freebayes.git</action>
+ # Eliminate the shell_command clone action so remaining actions can be processed correctly.
+ filtered_actions = actions[ 1: ]
return_code = handle_command( app, tool_dependency, install_dir, action_dict[ 'command' ] )
if return_code:
return
dir = package_name
+ else:
+ # We're handling a complex repository dependency where we only have a set_environment tag set.
+ # <action type="set_environment">
+ # <environment_variable name="PATH" action="prepend_to">$INSTALL_DIR/bin</environment_variable>
+ # </action>
+ filtered_actions = [ a for a in actions ]
+ dir = install_dir
if not os.path.exists( dir ):
os.makedirs( dir )
# The package has been down-loaded, so we can now perform all of the actions defined for building it.
with lcd( dir ):
- for action_tup in actions[ 1: ]:
+ for action_tup in filtered_actions:
action_type, action_dict = action_tup
current_dir = os.path.abspath( os.path.join( work_dir, dir ) )
if action_type == 'make_directory':
@@ -93,6 +105,8 @@
source_dir=os.path.join( action_dict[ 'source_directory' ] ),
destination_dir=os.path.join( action_dict[ 'destination_directory' ] ) )
elif action_type == 'move_file':
+ # TODO: Remove this hack that resets current_dir so that the pre-compiled bwa binary can be found.
+ # current_dir = '/Users/gvk/workspaces_2008/bwa/bwa-0.5.9'
common_util.move_file( current_dir=current_dir,
source=os.path.join( action_dict[ 'source' ] ),
destination_dir=os.path.join( action_dict[ 'destination' ] ) )
diff -r 618c34d9b2eab385e092c9ca2d7dd07b9ea31024 -r ea3da2000fa733a2d3ff5d5629dec58d3573645c lib/galaxy/tool_shed/tool_dependencies/install_util.py
--- a/lib/galaxy/tool_shed/tool_dependencies/install_util.py
+++ b/lib/galaxy/tool_shed/tool_dependencies/install_util.py
@@ -1,8 +1,9 @@
-import sys, os, subprocess, tempfile
+import sys, os, subprocess, tempfile, urllib2
import common_util
import fabric_util
from galaxy.tool_shed import encoding_util
from galaxy.model.orm import and_
+from galaxy.web import url_for
from galaxy import eggs
import pkg_resources
@@ -11,6 +12,9 @@
from elementtree import ElementTree, ElementInclude
from elementtree.ElementTree import Element, SubElement
+def clean_tool_shed_url( base_url ):
+ protocol, base = base_url.split( '://' )
+ return base.rstrip( '/' )
def create_or_update_tool_dependency( app, tool_shed_repository, name, version, type, status, set_status=True ):
# Called from Galaxy (never the tool shed) when a new repository is being installed or when an uninstalled repository is being reinstalled.
sa_session = app.model.context.current
@@ -28,6 +32,64 @@
sa_session.add( tool_dependency )
sa_session.flush()
return tool_dependency
+def create_temporary_tool_dependencies_config( tool_shed_url, name, owner, changeset_revision ):
+ """Make a call to the tool shed to get the required repository's tool_dependencies.xml file."""
+ url = url_join( tool_shed_url,
+ 'repository/get_tool_dependencies_config_contents?name=%s&owner=%s&changeset_revision=%s' % \
+ ( name, owner, changeset_revision ) )
+ response = urllib2.urlopen( url )
+ text = response.read()
+ response.close()
+ if text:
+ # Write the contents to a temporary file on disk so it can be reloaded and parsed.
+ fh = tempfile.NamedTemporaryFile( 'wb' )
+ tmp_filename = fh.name
+ fh.close()
+ fh = open( tmp_filename, 'wb' )
+ fh.write( text )
+ fh.close()
+ return tmp_filename
+ else:
+ message = "Unable to retrieve required tool_dependencies.xml file from the tool shed for revision "
+ message += "%s of installed repository %s owned by %s." % ( str( changeset_revision ), str( name ), str( owner ) )
+ raise Exception( message )
+ return None
+def get_absolute_path_to_file_in_repository( repo_files_dir, file_name ):
+ """Return the absolute path to a specified disk file contained in a repository."""
+ stripped_file_name = strip_path( file_name )
+ file_path = None
+ for root, dirs, files in os.walk( repo_files_dir ):
+ if root.find( '.hg' ) < 0:
+ for name in files:
+ if name == stripped_file_name:
+ return os.path.abspath( os.path.join( root, name ) )
+ return file_path
+def get_tool_shed_repository_by_tool_shed_name_owner_changeset_revision( app, tool_shed_url, name, owner, changeset_revision ):
+ sa_session = app.model.context.current
+ tool_shed = clean_tool_shed_url( tool_shed_url )
+ tool_shed_repository = sa_session.query( app.model.ToolShedRepository ) \
+ .filter( and_( app.model.ToolShedRepository.table.c.tool_shed == tool_shed,
+ app.model.ToolShedRepository.table.c.name == name,
+ app.model.ToolShedRepository.table.c.owner == owner,
+ app.model.ToolShedRepository.table.c.changeset_revision == changeset_revision ) ) \
+ .first()
+ if tool_shed_repository:
+ return tool_shed_repository
+ # The tool_shed_repository must have been updated to a newer changeset revision than the one defined in the repository_dependencies.xml file,
+ # so call the tool shed to get all appropriate newer changeset revisions.
+ text = get_updated_changeset_revisions_from_tool_shed( tool_shed_url, name, owner, changeset_revision )
+ if text:
+ changeset_revisions = listify( text )
+ for changeset_revision in changeset_revisions:
+ tool_shed_repository = sa_session.query( app.model.ToolShedRepository ) \
+ .filter( and_( app.model.ToolShedRepository.table.c.tool_shed == tool_shed,
+ app.model.ToolShedRepository.table.c.name == name,
+ app.model.ToolShedRepository.table.c.owner == owner,
+ app.model.ToolShedRepository.table.c.changeset_revision == changeset_revision ) ) \
+ .first()
+ if tool_shed_repository:
+ return tool_shed_repository
+ return None
def get_tool_dependency_by_name_type_repository( app, repository, name, type ):
sa_session = app.model.context.current
return sa_session.query( app.model.ToolDependency ) \
@@ -43,23 +105,83 @@
app.model.ToolDependency.table.c.version == version,
app.model.ToolDependency.table.c.type == type ) ) \
.first()
-def get_tool_dependency_install_dir( app, repository, type, name, version ):
- if type == 'package':
+def get_tool_dependency_install_dir( app, repository_name, repository_owner, repository_changeset_revision, tool_dependency_type, tool_dependency_name,
+ tool_dependency_version ):
+ if tool_dependency_type == 'package':
return os.path.abspath( os.path.join( app.config.tool_dependency_dir,
- name,
- version,
- repository.owner,
- repository.name,
- repository.installed_changeset_revision ) )
- if type == 'set_environment':
+ tool_dependency_name,
+ tool_dependency_version,
+ repository_owner,
+ repository_name,
+ repository_changeset_revision ) )
+ if tool_dependency_type == 'set_environment':
return os.path.abspath( os.path.join( app.config.tool_dependency_dir,
'environment_settings',
- name,
- repository.owner,
- repository.name,
- repository.installed_changeset_revision ) )
+ tool_dependency_name,
+ repository_owner,
+ repository_name,
+ repository_changeset_revision ) )
def get_tool_shed_repository_install_dir( app, tool_shed_repository ):
return os.path.abspath( tool_shed_repository.repo_files_directory( app ) )
+def get_updated_changeset_revisions_from_tool_shed( tool_shed_url, name, owner, changeset_revision ):
+ """Get all appropriate newer changeset revisions for the repository defined by the received tool_shed_url / name / owner combination."""
+ url = url_join( tool_shed_url,
+ 'repository/updated_changeset_revisions?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision ) )
+ response = urllib2.urlopen( url )
+ text = response.read()
+ response.close()
+ return text
+def handle_set_environment_entry_for_package( app, install_dir, tool_shed_repository, package_name, package_version, elem ):
+ action_dict = {}
+ actions = []
+ for package_elem in elem:
+ if package_elem.tag == 'install':
+ # Create the tool_dependency record in the database.
+ tool_dependency = create_or_update_tool_dependency( app=app,
+ tool_shed_repository=tool_shed_repository,
+ name=package_name,
+ version=package_version,
+ type='package',
+ status=app.model.ToolDependency.installation_status.INSTALLING,
+ set_status=True )
+ # Get the installation method version from a tag like: <install version="1.0">
+ package_install_version = package_elem.get( 'version', '1.0' )
+ if package_install_version == '1.0':
+ # Since the required tool dependency is installed for a repository dependency, all we need to do
+ # is inspect the <actions> tag set to find the <action type="set_environment"> tag.
+ for actions_elem in package_elem:
+ for action_elem in actions_elem:
+ action_type = action_elem.get( 'type', 'shell_command' )
+ if action_type == 'set_environment':
+ # <action type="set_environment">
+ # <environment_variable name="PYTHONPATH" action="append_to">$INSTALL_DIR/lib/python</environment_variable>
+ # <environment_variable name="PATH" action="prepend_to">$INSTALL_DIR/bin</environment_variable>
+ # </action>
+ env_var_dicts = []
+ for env_elem in action_elem:
+ if env_elem.tag == 'environment_variable':
+ env_var_dict = common_util.create_env_var_dict( env_elem, tool_dependency_install_dir=install_dir )
+ if env_var_dict:
+ env_var_dicts.append( env_var_dict )
+ if env_var_dicts:
+ action_dict[ env_elem.tag ] = env_var_dicts
+ actions.append( ( action_type, action_dict ) )
+ return tool_dependency, actions
+ return None, actions
+def install_and_build_package_via_fabric( app, tool_dependency, actions_dict ):
+ sa_session = app.model.context.current
+ try:
+ # There is currently only one fabric method.
+ fabric_util.install_and_build_package( app, tool_dependency, actions_dict )
+ except Exception, e:
+ tool_dependency.status = app.model.ToolDependency.installation_status.ERROR
+ tool_dependency.error_message = str( e )
+ sa_session.add( tool_dependency )
+ sa_session.flush()
+ if tool_dependency.status != app.model.ToolDependency.installation_status.ERROR:
+ tool_dependency.status = app.model.ToolDependency.installation_status.INSTALLED
+ sa_session.add( tool_dependency )
+ sa_session.flush()
def install_package( app, elem, tool_shed_repository, tool_dependencies=None ):
# The value of tool_dependencies is a partial or full list of ToolDependency records associated with the tool_shed_repository.
sa_session = app.model.context.current
@@ -69,18 +191,101 @@
package_version = elem.get( 'version', None )
if package_name and package_version:
if tool_dependencies:
- install_dir = get_tool_dependency_install_dir( app,
- repository=tool_shed_repository,
- type='package',
- name=package_name,
- version=package_version )
+ # Get the installation directory for tool dependencies that will be installed for the received tool_shed_repository.
+ install_dir = get_tool_dependency_install_dir( app=app,
+ repository_name=tool_shed_repository.name,
+ repository_owner=tool_shed_repository.owner,
+ repository_changeset_revision=tool_shed_repository.installed_changeset_revision,
+ tool_dependency_type='package',
+ tool_dependency_name=package_name,
+ tool_dependency_version=package_version )
if not os.path.exists( install_dir ):
for package_elem in elem:
- if package_elem.tag == 'install':
+ if package_elem.tag == 'repository':
+ # We have a complex repository dependency definition.
+ tool_shed = package_elem.attrib[ 'toolshed' ]
+ required_repository_name = package_elem.attrib[ 'name' ]
+ required_repository_owner = package_elem.attrib[ 'owner' ]
+ required_repository_changeset_revision = package_elem.attrib[ 'changeset_revision' ]
+ required_repository = get_tool_shed_repository_by_tool_shed_name_owner_changeset_revision( app,
+ tool_shed,
+ required_repository_name,
+ required_repository_owner,
+ required_repository_changeset_revision )
+ tmp_filename = None
+ if required_repository:
+ # Set this repository's tool dependency env.sh file with a path to the required repository's installed tool dependency package.
+ # We can get everything we need from the discovered installed required_repository.
+ if required_repository.status in [ app.model.ToolShedRepository.installation_status.DEACTIVATED,
+ app.model.ToolShedRepository.installation_status.INSTALLED ]:
+ # Define the installation directory for the required tool dependency in the required repository.
+ required_repository_package_install_dir = \
+ get_tool_dependency_install_dir( app=app,
+ repository_name=required_repository.name,
+ repository_owner=required_repository.owner,
+ repository_changeset_revision=required_repository.installed_changeset_revision,
+ tool_dependency_type='package',
+ tool_dependency_name=package_name,
+ tool_dependency_version=package_version )
+ assert os.path.exists( required_repository_package_install_dir ), \
+ 'Missing required tool dependency directory %s' % str( required_repository_package_install_dir )
+ repo_files_dir = required_repository.repo_files_directory( app )
+ tool_dependencies_config = get_absolute_path_to_file_in_repository( repo_files_dir, 'tool_dependencies.xml' )
+ if tool_dependencies_config:
+ config_to_use = tool_dependencies_config
+ else:
+ message = "Unable to locate required tool_dependencies.xml file for revision %s of installed repository %s owned by %s." % \
+ ( str( required_repository.changeset_revision ), str( required_repository.name ), str( required_repository.owner ) )
+ raise Exception( message )
+ else:
+ # Make a call to the tool shed to get the changeset revision to which the current value of required_repository_changeset_revision
+ # should be updated if it's not current.
+ text = get_updated_changeset_revisions_from_tool_shed( tool_shed_url=tool_shed,
+ name=required_repository_name,
+ owner=required_repository_owner,
+ changeset_revision=required_repository_changeset_revision )
+ if text:
+ updated_changeset_revisions = listify( text )
+ # The list of changeset revisions is in reverse order, so the newest will be first.
+ required_repository_changeset_revision = updated_changeset_revisions[ 0 ]
+ # Define the installation directory for the required tool dependency in the required repository.
+ required_repository_package_install_dir = \
+ get_tool_dependency_install_dir( app=app,
+ repository_name=required_repository_name,
+ repository_owner=required_repository_owner,
+ repository_changeset_revision=required_repository_changeset_revision,
+ tool_dependency_type='package',
+ tool_dependency_name=package_name,
+ tool_dependency_version=package_version )
+ # Make a call to the tool shed to get the required repository's tool_dependencies.xml file.
+ tmp_filename = create_temporary_tool_dependencies_config( tool_shed,
+ required_repository_name,
+ required_repository_owner,
+ required_repository_changeset_revision )
+ config_to_use = tmp_filename
+ tool_dependency, actions_dict = populate_actions_dict( app=app,
+ dependent_install_dir=install_dir,
+ required_install_dir=required_repository_package_install_dir,
+ tool_shed_repository=tool_shed_repository,
+ package_name=package_name,
+ package_version=package_version,
+ tool_dependencies_config=config_to_use )
+ if tmp_filename:
+ try:
+ os.remove( tmp_filename )
+ except:
+ pass
+ # Install and build the package via fabric.
+ install_and_build_package_via_fabric( app, tool_dependency, actions_dict )
+ else:
+ message = "Unable to locate required tool shed repository named %s owned by %s with revision %s." % \
+ ( str( name ), str( owner ), str( changeset_revision ) )
+ raise Exception( message )
+ elif package_elem.tag == 'install':
# <install version="1.0">
package_install_version = package_elem.get( 'version', '1.0' )
- tool_dependency = create_or_update_tool_dependency( app,
- tool_shed_repository,
+ tool_dependency = create_or_update_tool_dependency( app=app,
+ tool_shed_repository=tool_shed_repository,
name=package_name,
version=package_version,
type='package',
@@ -168,7 +373,7 @@
if env_elem.tag == 'environment_variable':
env_var_dict = common_util.create_env_var_dict( env_elem, tool_dependency_install_dir=install_dir )
if env_var_dict:
- env_var_dicts.append( env_var_dict )
+ env_var_dicts.append( env_var_dict )
if env_var_dicts:
action_dict[ env_elem.tag ] = env_var_dicts
else:
@@ -183,18 +388,56 @@
# run_proprietary_fabric_method( app, elem, proprietary_fabfile_path, install_dir, package_name=package_name )
raise Exception( 'Tool dependency installation using proprietary fabric scripts is not yet supported.' )
else:
- try:
- # There is currently only one fabric method.
- fabric_util.install_and_build_package( app, tool_dependency, actions_dict )
- except Exception, e:
- tool_dependency.status = app.model.ToolDependency.installation_status.ERROR
- tool_dependency.error_message = str( e )
- sa_session.add( tool_dependency )
- sa_session.flush()
- if tool_dependency.status != app.model.ToolDependency.installation_status.ERROR:
- tool_dependency.status = app.model.ToolDependency.installation_status.INSTALLED
- sa_session.add( tool_dependency )
- sa_session.flush()
+ install_and_build_package_via_fabric( app, tool_dependency, actions_dict )
+def listify( item ):
+ """
+ Make a single item a single item list, or return a list if passed a
+ list. Passing a None returns an empty list.
+ """
+ if not item:
+ return []
+ elif isinstance( item, list ):
+ return item
+ elif isinstance( item, basestring ) and item.count( ',' ):
+ return item.split( ',' )
+ else:
+ return [ item ]
+def populate_actions_dict( app, dependent_install_dir, required_install_dir, tool_shed_repository, package_name, package_version, tool_dependencies_config ):
+ """
+ Populate an actions dictionary that can be sent to fabric_util.install_and_build_package. This method handles the scenario where a tool_dependencies.xml
+ file defines a complex repository dependency. In this case, the tool dependency package will be installed in a separate repository and the tool dependency
+ defined for the dependent repository will use an environment_variable setting defined in it's env.sh file to locate the required package. This method
+ basically does what the install_via_fabric method does, but restricts it's activity to the <action type="set_environment"> tag set within the required
+ repository's tool_dependencies.xml file.
+ """
+ sa_session = app.model.context.current
+ if not os.path.exists( dependent_install_dir ):
+ os.makedirs( dependent_install_dir )
+ actions_dict = dict( install_dir=dependent_install_dir )
+ if package_name:
+ actions_dict[ 'package_name' ] = package_name
+ tool_dependency = None
+ action_dict = {}
+ if tool_dependencies_config:
+ required_td_tree = parse_xml( tool_dependencies_config )
+ required_td_root = required_td_tree.getroot()
+ for required_td_elem in required_td_root:
+ # Find the appropriate package name and version.
+ if required_td_elem.tag == 'package':
+ # <package name="bwa" version="0.5.9">
+ required_td_package_name = required_td_elem.get( 'name', None )
+ required_td_package_version = required_td_elem.get( 'version', None )
+ if required_td_package_name==package_name and required_td_package_version==package_version:
+ tool_dependency, actions = handle_set_environment_entry_for_package( app=app,
+ install_dir=required_install_dir,
+ tool_shed_repository=tool_shed_repository,
+ package_name=package_name,
+ package_version=package_version,
+ elem=required_td_elem )
+ if actions:
+ actions_dict[ 'actions' ] = actions
+ break
+ return tool_dependency, actions_dict
def run_proprietary_fabric_method( app, elem, proprietary_fabfile_path, install_dir, package_name=None, **kwd ):
"""
TODO: Handle this using the fabric api.
@@ -248,6 +491,10 @@
tmp_stderr = open( tmp_name, 'rb' )
message = '%s\n' % str( tmp_stderr.read() )
tmp_stderr.close()
+ try:
+ os.remove( tmp_name )
+ except:
+ pass
return returncode, message
def set_environment( app, elem, tool_shed_repository ):
"""
@@ -258,6 +505,11 @@
<environment_variable name="R_SCRIPT_PATH" action="set_to">$REPOSITORY_INSTALL_DIR</environment_variable></set_environment>
"""
+ # TODO: Add support for a repository dependency definition within this tool dependency type's tag set. This should look something like
+ # the following. See the implementation of support for this in the tool dependency package type's method above.
+ # <set_environment version="1.0">
+ # <repository toolshed="<tool shed>" name="<repository name>" owner="<repository owner>" changeset_revision="<changeset revision>" />
+ # </set_environment>
sa_session = app.model.context.current
tool_dependency = None
env_var_version = elem.get( 'version', '1.0' )
@@ -267,18 +519,20 @@
env_var_name = env_var_elem.get( 'name', None )
env_var_action = env_var_elem.get( 'action', None )
if env_var_name and env_var_action:
- install_dir = get_tool_dependency_install_dir( app,
- repository=tool_shed_repository,
- type='set_environment',
- name=env_var_name,
- version=None )
+ install_dir = get_tool_dependency_install_dir( app=app,
+ repository_name=tool_shed_repository.name,
+ repository_owner=tool_shed_repository.owner,
+ repository_changeset_revision=tool_shed_repository.installed_changeset_revision,
+ tool_dependency_type='set_environment',
+ tool_dependency_name=env_var_name,
+ tool_dependency_version=None )
tool_shed_repository_install_dir = get_tool_shed_repository_install_dir( app, tool_shed_repository )
env_var_dict = common_util.create_env_var_dict( env_var_elem, tool_shed_repository_install_dir=tool_shed_repository_install_dir )
if env_var_dict:
if not os.path.exists( install_dir ):
os.makedirs( install_dir )
- tool_dependency = create_or_update_tool_dependency( app,
- tool_shed_repository,
+ tool_dependency = create_or_update_tool_dependency( app=app,
+ tool_shed_repository=tool_shed_repository,
name=env_var_name,
version=None,
type='set_environment',
@@ -294,3 +548,22 @@
sa_session.add( tool_dependency )
sa_session.flush()
print 'Environment variable ', env_var_name, 'set in', install_dir
+def strip_path( fpath ):
+ if not fpath:
+ return fpath
+ try:
+ file_path, file_name = os.path.split( fpath )
+ except:
+ file_name = fpath
+ return file_name
+def parse_xml( file_name ):
+ """Returns a parsed xml tree."""
+ tree = ElementTree.parse( file_name )
+ root = tree.getroot()
+ ElementInclude.include( root )
+ return tree
+def url_join( *args ):
+ parts = []
+ for arg in args:
+ parts.append( arg.strip( '/' ) )
+ return '/'.join( parts )
diff -r 618c34d9b2eab385e092c9ca2d7dd07b9ea31024 -r ea3da2000fa733a2d3ff5d5629dec58d3573645c lib/galaxy/util/shed_util.py
--- a/lib/galaxy/util/shed_util.py
+++ b/lib/galaxy/util/shed_util.py
@@ -414,7 +414,7 @@
cleaned_repository_clone_url = suc.clean_repository_clone_url( repository_clone_url )
if not owner:
owner = get_repository_owner( cleaned_repository_clone_url )
- tool_shed = cleaned_repository_clone_url.split( 'repos' )[ 0 ].rstrip( '/' )
+ tool_shed = cleaned_repository_clone_url.split( '/repos/' )[ 0 ].rstrip( '/' )
for guid, tool_section_dicts in tool_panel_dict.items():
for tool_section_dict in tool_section_dicts:
tool_section = None
@@ -484,20 +484,6 @@
tool_section_dicts = generate_tool_section_dicts( tool_config=file_name, tool_sections=tool_sections )
tool_panel_dict[ guid ] = tool_section_dicts
return tool_panel_dict
-def generate_tool_path( repository_clone_url, changeset_revision ):
- """
- Generate a tool path that guarantees repositories with the same name will always be installed
- in different directories. The tool path will be of the form:
- <tool shed url>/repos/<repository owner>/<repository name>/<installed changeset revision>
- http://test@bx.psu.edu:9009/repos/test/filter
- """
- tmp_url = suc.clean_repository_clone_url( repository_clone_url )
- # Now tmp_url is something like: bx.psu.edu:9009/repos/some_username/column
- items = tmp_url.split( 'repos' )
- tool_shed_url = items[ 0 ]
- repo_path = items[ 1 ]
- tool_shed_url = suc.clean_tool_shed_url( tool_shed_url )
- return suc.url_join( tool_shed_url, 'repos', repo_path, changeset_revision )
def generate_tool_section_dicts( tool_config=None, tool_sections=None ):
tool_section_dicts = []
if tool_config is None:
@@ -529,6 +515,18 @@
else:
tool_section = None
return tool_section
+def generate_tool_shed_repository_install_dir( repository_clone_url, changeset_revision ):
+ """
+ Generate a repository installation directory that guarantees repositories with the same name will always be installed in different directories.
+ The tool path will be of the form: <tool shed url>/repos/<repository owner>/<repository name>/<installed changeset revision>
+ """
+ tmp_url = suc.clean_repository_clone_url( repository_clone_url )
+ # Now tmp_url is something like: bx.psu.edu:9009/repos/some_username/column
+ items = tmp_url.split( '/repos/' )
+ tool_shed_url = items[ 0 ]
+ repo_path = items[ 1 ]
+ tool_shed_url = suc.clean_tool_shed_url( tool_shed_url )
+ return suc.url_join( tool_shed_url, 'repos', repo_path, changeset_revision )
def get_config( config_file, repo, ctx, dir ):
"""Return the latest version of config_filename from the repository manifest."""
config_file = suc.strip_path( config_file )
@@ -821,14 +819,14 @@
readme_files_dict = json.from_json_string( raw_text )
return readme_files_dict
def get_repository_owner( cleaned_repository_url ):
- items = cleaned_repository_url.split( 'repos' )
+ items = cleaned_repository_url.split( '/repos/' )
repo_path = items[ 1 ]
if repo_path.startswith( '/' ):
repo_path = repo_path.replace( '/', '', 1 )
return repo_path.lstrip( '/' ).split( '/' )[ 0 ]
def get_repository_owner_from_clone_url( repository_clone_url ):
tmp_url = suc.clean_repository_clone_url( repository_clone_url )
- tool_shed = tmp_url.split( 'repos' )[ 0 ].rstrip( '/' )
+ tool_shed = tmp_url.split( '/repos/' )[ 0 ].rstrip( '/' )
return get_repository_owner( tmp_url )
def get_required_repo_info_dicts( tool_shed_url, repo_info_dicts ):
"""
diff -r 618c34d9b2eab385e092c9ca2d7dd07b9ea31024 -r ea3da2000fa733a2d3ff5d5629dec58d3573645c lib/galaxy/util/shed_util_common.py
--- a/lib/galaxy/util/shed_util_common.py
+++ b/lib/galaxy/util/shed_util_common.py
@@ -1202,7 +1202,10 @@
app.config.tool_data_table_config_path = original_tool_data_table_config_path
return metadata_dict, invalid_file_tups
def generate_package_dependency_metadata( app, elem, tool_dependencies_dict ):
- """The value of package_name must match the value of the "package" type in the tool config's <requirements> tag set."""
+ """
+ Generate the metadata for a tool dependencies package defined for a repository. The value of package_name must match the value of the "package"
+ type in the tool config's <requirements> tag set. This method is called from both Galaxy and the tool shed.
+ """
repository_dependency_tup = []
requirements_dict = {}
error_message = ''
@@ -1217,9 +1220,9 @@
requirements_dict[ 'readme' ] = sub_elem.text
elif sub_elem.tag == 'repository':
# We have a complex repository dependency.
- current_rd_tups, error_message = handle_repository_elem_for_tool_shed( app=app,
- repository_elem=sub_elem,
- repository_dependencies_tups=None )
+ current_rd_tups, error_message = handle_repository_elem( app=app,
+ repository_elem=sub_elem,
+ repository_dependencies_tups=None )
repository_dependency_tup = current_rd_tups[ 0 ]
if requirements_dict:
dependency_key = '%s/%s' % ( package_name, package_version )
@@ -1274,7 +1277,7 @@
is_valid = False
if is_valid:
for repository_elem in root.findall( 'repository' ):
- current_rd_tups, error_message = handle_repository_elem_for_tool_shed( app, repository_elem, repository_dependencies_tups )
+ current_rd_tups, error_message = handle_repository_elem( app, repository_elem, repository_dependencies_tups )
if error_message:
log.debug( error_message )
return metadata_dict, error_message
@@ -1477,7 +1480,7 @@
metadata_dict[ 'workflows' ] = [ ( relative_path, exported_workflow_dict ) ]
return metadata_dict
def get_absolute_path_to_file_in_repository( repo_files_dir, file_name ):
- """Return the absolute path to a specified disk file containe in a repository."""
+ """Return the absolute path to a specified disk file contained in a repository."""
stripped_file_name = strip_path( file_name )
file_path = None
for root, dirs, files in os.walk( repo_files_dir ):
@@ -1677,8 +1680,8 @@
return None
def get_next_downloadable_changeset_revision( repository, repo, after_changeset_revision ):
"""
- Return the installable changeset_revision in the repository changelog after to the changeset to which after_changeset_revision
- refers. If there isn't one, return None.
+ Return the installable changeset_revision in the repository changelog after the changeset to which after_changeset_revision refers. If there
+ isn't one, return None.
"""
changeset_revisions = get_ordered_downloadable_changeset_revisions( repository, repo )
if len( changeset_revisions ) == 1:
@@ -2157,7 +2160,7 @@
.first()
def get_tool_shed_from_clone_url( repository_clone_url ):
tmp_url = clean_repository_clone_url( repository_clone_url )
- return tmp_url.split( 'repos' )[ 0 ].rstrip( '/' )
+ return tmp_url.split( '/repos/' )[ 0 ].rstrip( '/' )
def get_updated_changeset_revisions_for_repository_dependencies( trans, key_rd_dicts ):
updated_key_rd_dicts = []
for key_rd_dict in key_rd_dicts:
@@ -2411,6 +2414,67 @@
all_repository_dependencies=all_repository_dependencies,
handled_key_rd_dicts=handled_key_rd_dicts,
circular_repository_dependencies=circular_repository_dependencies )
+def handle_repository_elem( app, repository_elem, repository_dependencies_tups ):
+ """
+ Process the received repository_elem which is a <repository> tag either from a repository_dependencies.xml file or a tool_dependencies.xml file.
+ If the former, we're generating repository dependencies metadata for a repository in the tool shed. If the latter, we're generating package
+ dependency metadata with in Galaxy or the tool shed.
+ """
+ if repository_dependencies_tups is None:
+ new_rd_tups = []
+ else:
+ new_rd_tups = [ rdt for rdt in repository_dependencies_tups ]
+ error_message = ''
+ sa_session = app.model.context.current
+ toolshed = repository_elem.attrib[ 'toolshed' ]
+ name = repository_elem.attrib[ 'name' ]
+ owner = repository_elem.attrib[ 'owner' ]
+ changeset_revision = repository_elem.attrib[ 'changeset_revision' ]
+ user = None
+ repository = None
+ if app.name == 'galaxy':
+ # We're in Galaxy.
+ try:
+ repository = sa_session.query( app.model.ToolShedRepository ) \
+ .filter( and_( app.model.ToolShedRepository.table.c.name == name,
+ app.model.ToolShedRepository.table.c.owner == owner ) ) \
+ .first()
+ except:
+ error_message = "Invalid name %s or owner %s defined for repository. Repository dependencies will be ignored." % ( name, owner )
+ log.debug( error_message )
+ return new_rd_tups, error_message
+ repository_dependencies_tup = ( toolshed, name, owner, changeset_revision )
+ if repository_dependencies_tup not in new_rd_tups:
+ new_rd_tups.append( repository_dependencies_tup )
+ else:
+ # We're in the tool shed.
+ if tool_shed_is_this_tool_shed( toolshed ):
+ try:
+ user = sa_session.query( app.model.User ) \
+ .filter( app.model.User.table.c.username == owner ) \
+ .one()
+ except Exception, e:
+ error_message = "Invalid owner %s defined for repository %s. Repository dependencies will be ignored." % ( owner, name )
+ log.debug( error_message )
+ return new_rd_tups, error_message
+ try:
+ repository = sa_session.query( app.model.Repository ) \
+ .filter( and_( app.model.Repository.table.c.name == name,
+ app.model.Repository.table.c.user_id == user.id ) ) \
+ .first()
+ except:
+ error_message = "Invalid name %s or owner %s defined for repository. Repository dependencies will be ignored." % ( name, owner )
+ log.debug( error_message )
+ return new_rd_tups, error_message
+ repository_dependencies_tup = ( toolshed, name, owner, changeset_revision )
+ if repository_dependencies_tup not in new_rd_tups:
+ new_rd_tups.append( repository_dependencies_tup )
+ else:
+ # Repository dependencies are currentlhy supported within a single tool shed.
+ error_message = "Invalid tool shed %s defined for repository %s. " % ( toolshed, name )
+ error_message += "Repository dependencies are currently supported within a single tool shed, so your definition will be ignored."
+ log.debug( error_message )
+ return new_rd_tups, error_message
def handle_sample_files_and_load_tool_from_disk( trans, repo_files_dir, tool_config_filepath, work_dir ):
# Copy all sample files from disk to a temporary directory since the sample files may be in multiple directories.
message = ''
@@ -2487,54 +2551,6 @@
if is_orphan_in_tool_shed:
return True
return False
-def handle_repository_elem_for_tool_shed( app, repository_elem, repository_dependencies_tups ):
- if repository_dependencies_tups is None:
- new_rd_tups = []
- else:
- new_rd_tups = [ rdt for rdt in repository_dependencies_tups ]
- error_message = ''
- sa_session = app.model.context.current
- toolshed = repository_elem.attrib[ 'toolshed' ]
- name = repository_elem.attrib[ 'name' ]
- owner = repository_elem.attrib[ 'owner' ]
- changeset_revision = repository_elem.attrib[ 'changeset_revision' ]
- user = None
- repository = None
- if tool_shed_is_this_tool_shed( toolshed ):
- try:
- user = sa_session.query( app.model.User ) \
- .filter( app.model.User.table.c.username == owner ) \
- .one()
- except Exception, e:
- error_message = "Invalid owner %s defined for repository %s. Repository dependencies will be ignored." % ( owner, name )
- log.debug( error_message )
- return new_rd_tups, error_message
- if user:
- try:
- repository = sa_session.query( app.model.Repository ) \
- .filter( and_( app.model.Repository.table.c.name == name,
- app.model.Repository.table.c.user_id == user.id ) ) \
- .first()
- except:
- error_message = "Invalid name %s or owner %s defined for repository. Repository dependencies will be ignored." % ( name, owner )
- log.debug( error_message )
- return new_rd_tups, error_message
- if repository:
- repository_dependencies_tup = ( toolshed, name, owner, changeset_revision )
- if repository_dependencies_tup not in new_rd_tups:
- new_rd_tups.append( repository_dependencies_tup )
- else:
- error_message = "Invalid name %s or owner %s defined for repository. Repository dependencies will be ignored." % ( name, owner )
- log.debug( error_message )
- else:
- error_message = "Invalid owner %s defined for owner of repository %s. Repository dependencies will be ignored." % ( owner, name )
- log.debug( error_message )
- else:
- # Repository dependencies are currentlhy supported within a single tool shed.
- error_message = "Invalid tool shed %s defined for repository %s. " % ( toolshed, name )
- error_message += "Repository dependencies are currently supported within a single tool shed, so your definition will be ignored."
- log.debug( error_message )
- return new_rd_tups, error_message
def has_previous_repository_reviews( trans, repository, changeset_revision ):
"""Determine if a repository has a changeset revision review prior to the received changeset revision."""
repo = hg.repository( get_configured_ui(), repository.repo_path( trans.app ) )
@@ -2588,7 +2604,22 @@
return True
return False
def is_downloadable( metadata_dict ):
- return 'datatypes' in metadata_dict or 'repository_dependencies' in metadata_dict or 'tools' in metadata_dict or 'workflows' in metadata_dict
+ if 'datatypes' in metadata_dict:
+ # We have proprietary datatypes.
+ return True
+ if 'repository_dependencies' in metadata_dict:
+ # We have repository_dependencies.
+ return True
+ if 'tools' in metadata_dict:
+ # We have tools.
+ return True
+ if 'tool_dependencies' in metadata_dict:
+ # We have tool dependencies, and perhaps only tool dependencies!
+ return True
+ if 'workflows' in metadata_dict:
+ # We have exported workflows.
+ return True
+ return False
def initialize_all_repository_dependencies( current_repository_key, repository_dependencies_dict, all_repository_dependencies ):
# Initialize the all_repository_dependencies dictionary. It's safe to assume that current_repository_key in this case will have a value.
all_repository_dependencies[ 'root_key' ] = current_repository_key
@@ -3322,7 +3353,7 @@
return ''.join( translated )
return text
def tool_shed_from_repository_clone_url( repository_clone_url ):
- return clean_repository_clone_url( repository_clone_url ).split( 'repos' )[ 0 ].rstrip( '/' )
+ return clean_repository_clone_url( repository_clone_url ).split( '/repos/' )[ 0 ].rstrip( '/' )
def tool_shed_is_this_tool_shed( toolshed_base_url ):
return toolshed_base_url.rstrip( '/' ) == str( url_for( '/', qualified=True ) ).rstrip( '/' )
def translate_string( raw_text, to_html=True ):
diff -r 618c34d9b2eab385e092c9ca2d7dd07b9ea31024 -r ea3da2000fa733a2d3ff5d5629dec58d3573645c lib/galaxy/webapps/community/controllers/repository.py
--- a/lib/galaxy/webapps/community/controllers/repository.py
+++ b/lib/galaxy/webapps/community/controllers/repository.py
@@ -1466,7 +1466,7 @@
return repo_info_dict
@web.expose
def get_tool_dependencies( self, trans, **kwd ):
- """Handle a request from a Galaxy instance."""
+ """Handle a request from a Galaxy instance to get the tool_dependencies entry from the metadata for a specified changeset revision."""
params = util.Params( kwd )
name = params.get( 'name', None )
owner = params.get( 'owner', None )
@@ -1481,6 +1481,26 @@
return encoding_util.tool_shed_encode( tool_dependencies )
return ''
@web.expose
+ def get_tool_dependencies_config_contents( self, trans, **kwd ):
+ """Handle a request from a Galaxy instance to get the tool_dependencies.xml file contents for a specified changeset revision."""
+ params = util.Params( kwd )
+ name = params.get( 'name', None )
+ owner = params.get( 'owner', None )
+ changeset_revision = params.get( 'changeset_revision', None )
+ repository = suc.get_repository_by_name_and_owner( trans, name, owner )
+ # TODO: We're currently returning the tool_dependencies.xml file that is available on disk. We need to enhance this process
+ # to retrieve older versions of the tool-dependencies.xml file from the repository manafest.
+ repo_dir = repository.repo_path( trans.app )
+ # Get the tool_dependencies.xml file from disk.
+ tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', repo_dir )
+ # Return the encoded contents of the tool_dependencies.xml file.
+ if tool_dependencies_config:
+ tool_dependencies_config_file = open( tool_dependencies_config, 'rb' )
+ contents = tool_dependencies_config_file.read()
+ tool_dependencies_config_file.close()
+ return contents
+ return ''
+ @web.expose
def get_tool_versions( self, trans, **kwd ):
"""
For each valid /downloadable change set (up to the received changeset_revision) in the repository's change log, append the change
@@ -1505,7 +1525,7 @@
return ''
@web.json
def get_updated_repository_information( self, trans, name, owner, changeset_revision, **kwd ):
- """Generate a disctionary that contains the information about a repository that is necessary for installing it into a local Galaxy instance."""
+ """Generate a dictionary that contains the information about a repository that is necessary for installing it into a local Galaxy instance."""
repository = suc.get_repository_by_name_and_owner( trans, name, owner )
repository_id = trans.security.encode_id( repository.id )
repository_clone_url = suc.generate_clone_url_for_repository_in_tool_shed( trans, repository )
@@ -2079,7 +2099,7 @@
repository = suc.get_repository_by_name_and_owner( trans, name, owner )
repo_dir = repository.repo_path( trans.app )
repo = hg.repository( suc.get_configured_ui(), repo_dir )
- # Get the lower bound changeset revision
+ # Get the lower bound changeset revision.
lower_bound_changeset_revision = suc.get_previous_downloadable_changset_revision( repository, repo, changeset_revision )
# Build the list of changeset revision hashes.
changeset_hashes = []
@@ -2404,6 +2424,35 @@
if list:
return ','.join( list )
return ''
+ @web.expose
+ def updated_changeset_revisions( self, trans, **kwd ):
+ """
+ Handle a request from a local Galaxy instance to retrieve the lsit of changeset revisions to which an installed repository can be updated. This
+ method will return a string of comma-separated changeset revision hashes for all available updates to the received changeset revision. Among
+ other things , this method handles the scenario where an installed tool shed repository's tool_dependency definition file defines a changeset
+ revision for a complex repository dependency that is outdated. In other words, a defined changeset revision is older than the current changeset
+ revision for the required repository, making it impossible to discover the repository without knowledge of revisions to which it could have been
+ updated.
+ """
+ params = util.Params( kwd )
+ name = params.get( 'name', None )
+ owner = params.get( 'owner', None )
+ changeset_revision = params.get( 'changeset_revision', None )
+ repository = suc.get_repository_by_name_and_owner( trans, name, owner )
+ repo_dir = repository.repo_path( trans.app )
+ repo = hg.repository( suc.get_configured_ui(), repo_dir )
+ # Get the upper bound changeset revision.
+ upper_bound_changeset_revision = suc.get_next_downloadable_changeset_revision( repository, repo, changeset_revision )
+ # Build the list of changeset revision hashes defining each available update up to, but excluding, upper_bound_changeset_revision.
+ changeset_hashes = []
+ for changeset in suc.reversed_lower_upper_bounded_changelog( repo, changeset_revision, upper_bound_changeset_revision ):
+ # Make sure to exclude upper_bound_changeset_revision.
+ if changeset != upper_bound_changeset_revision:
+ changeset_hashes.append( str( repo.changectx( changeset ) ) )
+ if changeset_hashes:
+ changeset_hashes_str = ','.join( changeset_hashes )
+ return changeset_hashes_str
+ return ''
def __validate_repository_name( self, name, user ):
# Repository names must be unique for each user, must be at least four characters
# in length and must contain only lower-case letters, numbers, and the '_' character.
diff -r 618c34d9b2eab385e092c9ca2d7dd07b9ea31024 -r ea3da2000fa733a2d3ff5d5629dec58d3573645c lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -890,7 +890,7 @@
shed_util.update_tool_shed_repository_status( trans.app, tool_shed_repository, trans.model.ToolShedRepository.installation_status.CLONING )
repo_info_tuple = repo_info_dict[ tool_shed_repository.name ]
description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, tool_dependencies = repo_info_tuple
- relative_clone_dir = shed_util.generate_tool_path( repository_clone_url, tool_shed_repository.installed_changeset_revision )
+ relative_clone_dir = shed_util.generate_tool_shed_repository_install_dir( repository_clone_url, tool_shed_repository.installed_changeset_revision )
clone_dir = os.path.join( tool_path, relative_clone_dir )
relative_install_dir = os.path.join( relative_clone_dir, tool_shed_repository.name )
install_dir = os.path.join( tool_path, relative_install_dir )
@@ -1416,7 +1416,8 @@
install_tool_dependencies = CheckboxField.is_checked( kwd.get( 'install_tool_dependencies', '' ) )
shed_tool_conf, tool_path, relative_install_dir = suc.get_tool_panel_config_tool_path_install_dir( trans.app, tool_shed_repository )
repository_clone_url = suc.generate_clone_url_for_installed_repository( trans.app, tool_shed_repository )
- clone_dir = os.path.join( tool_path, shed_util.generate_tool_path( repository_clone_url, tool_shed_repository.installed_changeset_revision ) )
+ clone_dir = os.path.join( tool_path, shed_util.generate_tool_shed_repository_install_dir( repository_clone_url,
+ tool_shed_repository.installed_changeset_revision ) )
relative_install_dir = os.path.join( clone_dir, tool_shed_repository.name )
tool_shed_url = suc.get_url_from_repository_tool_shed( trans.app, tool_shed_repository )
tool_section = None
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9f2b4091e1e5/
changeset: 9f2b4091e1e5
user: Richard Park
date: 2013-01-30 21:48:54
summary: Fixed error when retrieving workflows via API. Added additional tab to lines 88 and 89, to fix error when trying to refer to variable "step."
affected #: 1 file
diff -r 2fcef846289917ccf394bb2fabba8f36d55d0039 -r 9f2b4091e1e5114c8bfc692ce0e685cc75ada39b lib/galaxy/webapps/galaxy/api/workflows.py
--- a/lib/galaxy/webapps/galaxy/api/workflows.py
+++ b/lib/galaxy/webapps/galaxy/api/workflows.py
@@ -85,8 +85,8 @@
'type': step.type,
'tool_id': step.tool_id,
'input_steps': {}}
- for conn in step.input_connections:
- steps[step.id]['input_steps'][conn.input_name] = {'source_step': conn.output_step_id,
+ for conn in step.input_connections:
+ steps[step.id]['input_steps'][conn.input_name] = {'source_step': conn.output_step_id,
'step_output': conn.output_name}
item['steps'] = steps
return item
https://bitbucket.org/galaxy/galaxy-central/commits/618c34d9b2ea/
changeset: 618c34d9b2ea
user: dannon
date: 2013-01-30 21:57:10
summary: Merge Pull Request #114 https://bitbucket.org/galaxy/galaxy-central/pull-request/114/fixed-error-wh…
Adjusted spacing.
affected #: 1 file
diff -r a1d543da698d3d127cd9d7fedd61bd1ac5a19872 -r 618c34d9b2eab385e092c9ca2d7dd07b9ea31024 lib/galaxy/webapps/galaxy/api/workflows.py
--- a/lib/galaxy/webapps/galaxy/api/workflows.py
+++ b/lib/galaxy/webapps/galaxy/api/workflows.py
@@ -85,9 +85,9 @@
'type': step.type,
'tool_id': step.tool_id,
'input_steps': {}}
- for conn in step.input_connections:
- steps[step.id]['input_steps'][conn.input_name] = {'source_step': conn.output_step_id,
- 'step_output': conn.output_name}
+ for conn in step.input_connections:
+ steps[step.id]['input_steps'][conn.input_name] = {'source_step': conn.output_step_id,
+ 'step_output': conn.output_name}
item['steps'] = steps
return item
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
30 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a1d543da698d/
changeset: a1d543da698d
user: james_taylor
date: 2013-01-30 16:32:16
summary: web.framework: remove stray print
affected #: 1 file
diff -r 2fcef846289917ccf394bb2fabba8f36d55d0039 -r a1d543da698d3d127cd9d7fedd61bd1ac5a19872 lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py
+++ b/lib/galaxy/web/framework/__init__.py
@@ -278,7 +278,6 @@
if not( fname.startswith( "_" ) ) and fname.endswith( ".py" ):
name = fname[:-3]
module_name = package_name + "." + name
- print package_name, name, module_name
try:
module = import_module( module_name )
except ControllerUnavailable, exc:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/fdd9dd36d6e6/
changeset: fdd9dd36d6e6
user: inithello
date: 2013-01-30 20:54:41
summary: Enable specifying the location of the migrated tools' XML file.
affected #: 1 file
diff -r 43fa4cb72e0fdc207a07fc4c6402273ca4bd4fc6 -r fdd9dd36d6e6bdd17ecaa219c15a6afeb047748c lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -57,7 +57,7 @@
self.test_conf = resolve_path( kwargs.get( "test_conf", "" ), self.root )
# The value of migrated_tools_config is the file reserved for containing only those tools that have been eliminated from the distribution
# and moved to the tool shed.
- self.migrated_tools_config = resolve_path( "migrated_tools_conf.xml", self.root )
+ self.migrated_tools_config = resolve_path( kwargs.get( 'migrated_tools_config', 'migrated_tools_conf.xml' ), self.root )
if 'tool_config_file' in kwargs:
tcf = kwargs[ 'tool_config_file' ]
elif 'tool_config_files' in kwargs:
https://bitbucket.org/galaxy/galaxy-central/commits/8f56f551b194/
changeset: 8f56f551b194
user: inithello
date: 2013-01-30 20:55:08
summary: Enable running tool shed functional tests with run_functional_tests.sh.
affected #: 1 file
diff -r fdd9dd36d6e6bdd17ecaa219c15a6afeb047748c -r 8f56f551b194ef92029b88c5a774bf3d13220af3 run_functional_tests.sh
--- a/run_functional_tests.sh
+++ b/run_functional_tests.sh
@@ -6,11 +6,13 @@
if [ ! $1 ]; then
python ./scripts/functional_tests.py -v --with-nosehtml --html-report-file run_functional_tests.html --exclude="^get" functional
elif [ $1 = 'help' ]; then
- echo "'run_functional_tests.sh' for testing all the tools in functional directory"
- echo "'run_functional_tests.sh aaa' for testing one test case of 'aaa' ('aaa' is the file name with path)"
- echo "'run_functional_tests.sh -id bbb' for testing one tool with id 'bbb' ('bbb' is the tool id)"
- echo "'run_functional_tests.sh -sid ccc' for testing one section with sid 'ccc' ('ccc' is the string after 'section::')"
- echo "'run_functional_tests.sh -list' for listing all the tool ids"
+ echo "'run_functional_tests.sh' for testing all the tools in functional directory"
+ echo "'run_functional_tests.sh aaa' for testing one test case of 'aaa' ('aaa' is the file name with path)"
+ echo "'run_functional_tests.sh -id bbb' for testing one tool with id 'bbb' ('bbb' is the tool id)"
+ echo "'run_functional_tests.sh -sid ccc' for testing one section with sid 'ccc' ('ccc' is the string after 'section::')"
+ echo "'run_functional_tests.sh -list' for listing all the tool ids"
+ echo "'run_functional_tests.sh -toolshed' for running all the test scripts in the ./test/tool_shed/functional directory"
+ echo "'run_functional_tests.sh -toolshed testscriptname' for running one test script named testscriptname in the .test/tool_shed/functional directory"
elif [ $1 = '-id' ]; then
python ./scripts/functional_tests.py -v functional.test_toolbox:TestForTool_$2 --with-nosehtml --html-report-file run_functional_tests.html
elif [ $1 = '-sid' ]; then
@@ -38,6 +40,12 @@
else
python ./scripts/functional_tests.py -v functional.test_toolbox --with-nosehtml --html-report-file run_functional_tests.html -installed
fi
+elif [ $1 = '-toolshed' ]; then
+ if [ ! $2 ]; then
+ python ./test/tool_shed/functional_tests.py -v --with-nosehtml --html-report-file ./test/tool_shed/run_functional_tests.html ./test/tool_shed/functional
+ else
+ python ./test/tool_shed/functional_tests.py -v --with-nosehtml --html-report-file ./test/tool_shed/run_functional_tests.html $2
+ fi
else
python ./scripts/functional_tests.py -v --with-nosehtml --html-report-file run_functional_tests.html $1
fi
https://bitbucket.org/galaxy/galaxy-central/commits/2fcef8462899/
changeset: 2fcef8462899
user: inithello
date: 2013-01-30 20:57:16
summary: Pass in a temporary file as migrated_tools_conf, so repositories without tools end up in the right location.
affected #: 1 file
diff -r 8f56f551b194ef92029b88c5a774bf3d13220af3 -r 2fcef846289917ccf394bb2fabba8f36d55d0039 test/tool_shed/functional_tests.py
--- a/test/tool_shed/functional_tests.py
+++ b/test/tool_shed/functional_tests.py
@@ -124,6 +124,7 @@
galaxy_tool_data_table_conf_file = os.environ.get( 'GALAXY_TEST_TOOL_DATA_TABLE_CONF', os.path.join( tool_shed_test_tmp_dir, 'tool_data_table_conf.xml' ) )
galaxy_tool_conf_file = os.environ.get( 'GALAXY_TEST_TOOL_CONF', os.path.join( tool_shed_test_tmp_dir, 'test_tool_conf.xml' ) )
galaxy_shed_tool_conf_file = os.environ.get( 'GALAXY_TEST_SHED_TOOL_CONF', os.path.join( tool_shed_test_tmp_dir, 'test_shed_tool_conf.xml' ) )
+ galaxy_migrated_tool_conf_file = os.environ.get( 'GALAXY_TEST_MIGRATED_TOOL_CONF', os.path.join( tool_shed_test_tmp_dir, 'test_migrated_tool_conf.xml' ) )
galaxy_tool_sheds_conf_file = os.environ.get( 'GALAXY_TEST_TOOL_SHEDS_CONF', os.path.join( tool_shed_test_tmp_dir, 'test_sheds_conf.xml' ) )
if 'GALAXY_TEST_TOOL_DATA_PATH' in os.environ:
tool_data_path = os.environ.get( 'GALAXY_TEST_TOOL_DATA_PATH' )
@@ -141,6 +142,7 @@
new_repos_path = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
galaxy_tempfiles = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
galaxy_shed_tool_path = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
+ galaxy_migrated_tool_path = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
galaxy_tool_dependency_dir = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
os.environ[ 'GALAXY_TEST_TOOL_DEPENDENCY_DIR' ] = galaxy_tool_dependency_dir
if 'TOOL_SHED_TEST_DBURI' in os.environ:
@@ -258,6 +260,9 @@
shed_tool_conf_template_parser = string.Template( shed_tool_conf_xml_template )
shed_tool_conf_xml = shed_tool_conf_template_parser.safe_substitute( shed_tool_path=galaxy_shed_tool_path )
file( galaxy_shed_tool_conf_file, 'w' ).write( shed_tool_conf_xml )
+ # Generate the migrated_tool_conf.xml file.
+ migrated_tool_conf_xml = shed_tool_conf_template_parser.safe_substitute( shed_tool_path=galaxy_migrated_tool_path )
+ file( galaxy_migrated_tool_conf_file, 'w' ).write( migrated_tool_conf_xml )
os.environ[ 'GALAXY_TEST_SHED_TOOL_CONF' ] = galaxy_shed_tool_conf_file
# ---- Build Galaxy Application --------------------------------------------------
@@ -275,6 +280,7 @@
tool_data_path = tool_data_path,
shed_tool_path = galaxy_shed_tool_path,
update_integrated_tool_panel = False,
+ migrated_tools_config = galaxy_migrated_tool_conf_file,
tool_config_file = [ galaxy_tool_conf_file, galaxy_shed_tool_conf_file ],
tool_sheds_config_file = galaxy_tool_sheds_conf_file,
datatype_converters_config_file = "datatype_converters_conf.xml.sample",
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Add a util.move_merge() function that makes moving directories more consistent.
by Bitbucket 30 Jan '13
by Bitbucket 30 Jan '13
30 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/43fa4cb72e0f/
changeset: 43fa4cb72e0f
user: dan
date: 2013-01-30 19:49:43
summary: Add a util.move_merge() function that makes moving directories more consistent.
affected #: 1 file
diff -r a9cbfdfeff11e2e2595b37825584216441a7a6d1 -r 43fa4cb72e0fdc207a07fc4c6402273ca4bd4fc6 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -2,7 +2,7 @@
Utility functions used systemwide.
"""
-import logging, threading, random, string, re, binascii, pickle, time, datetime, math, re, os, sys, tempfile, stat, grp, smtplib, errno
+import logging, threading, random, string, re, binascii, pickle, time, datetime, math, re, os, sys, tempfile, stat, grp, smtplib, errno, shutil
from email.MIMEText import MIMEText
# Older py compatibility
@@ -737,6 +737,18 @@
else:
raise e
+def move_merge( source, target ):
+ #when using shutil and moving a directory, if the target exists,
+ #then the directory is placed inside of it
+ #if the target doesn't exist, then the target is made into the directory
+ #this makes it so that the target is always the target, and if it exists,
+ #the source contents are moved into the target
+ if os.path.isdir( source ) and os.path.exists( target ) and os.path.isdir( target ):
+ for name in os.listdir( source ):
+ move_merge( os.path.join( source, name ), os.path.join( target, name ) )
+ else:
+ return shutil.move( source, target )
+
galaxy_root_path = os.path.join(__path__[0], "..","..","..")
# The dbnames list is used in edit attributes and the upload tool
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b69934e3fa69/
changeset: b69934e3fa69
user: dan
date: 2013-01-30 19:40:22
summary: Add a util.force_symlink() helper method.
affected #: 1 file
diff -r ea27314cf43c60a2a3f20220b9642cc254f6baa1 -r b69934e3fa691cd24785b3c4a02bb81a154a4856 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -727,6 +727,16 @@
s.sendmail( frm, to, msg.as_string() )
s.quit()
+def force_symlink( source, link_name ):
+ try:
+ os.symlink( source, link_name )
+ except OSError, e:
+ if e.errno == errno.EEXIST:
+ os.remove( link_name )
+ os.symlink( source, link_name )
+ else:
+ raise e
+
galaxy_root_path = os.path.join(__path__[0], "..","..","..")
# The dbnames list is used in edit attributes and the upload tool
https://bitbucket.org/galaxy/galaxy-central/commits/a9cbfdfeff11/
changeset: a9cbfdfeff11
user: dan
date: 2013-01-30 19:40:23
summary: Allow DiskObjectStore.update_from_file() to optionally preserve symlinks.
affected #: 1 file
diff -r b69934e3fa691cd24785b3c4a02bb81a154a4856 -r a9cbfdfeff11e2e2595b37825584216441a7a6d1 lib/galaxy/objectstore/__init__.py
--- a/lib/galaxy/objectstore/__init__.py
+++ b/lib/galaxy/objectstore/__init__.py
@@ -342,11 +342,17 @@
def update_from_file(self, obj, file_name=None, create=False, **kwargs):
""" `create` parameter is not used in this implementation """
+ preserve_symlinks = kwargs.pop( 'preserve_symlinks', False )
+ #FIXME: symlinks and the object store model may not play well together
+ #these should be handled better, e.g. registering the symlink'd file as an object
if create:
self.create(obj, **kwargs)
if file_name and self.exists(obj, **kwargs):
try:
- shutil.copy(file_name, self.get_filename(obj, **kwargs))
+ if preserve_symlinks and os.path.islink( file_name ):
+ util.force_symlink( os.readlink( file_name ), self.get_filename( obj, **kwargs ) )
+ else:
+ shutil.copy( file_name, self.get_filename( obj, **kwargs ) )
except IOError, ex:
log.critical('Error copying %s to %s: %s' % (file_name,
self._get_filename(obj, **kwargs), ex))
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Show Galaxy Tool Version (job.tool_version) in addition to Tool Version (hda.tool_version) in dataset show_params.
by Bitbucket 30 Jan '13
by Bitbucket 30 Jan '13
30 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ea27314cf43c/
changeset: ea27314cf43c
user: dan
date: 2013-01-30 19:30:00
summary: Show Galaxy Tool Version (job.tool_version) in addition to Tool Version (hda.tool_version) in dataset show_params.
affected #: 1 file
diff -r 95e33df0ae0332e04f14646abbf77c02672ef23a -r ea27314cf43c60a2a3f20220b9642cc254f6baa1 templates/show_params.mako
--- a/templates/show_params.mako
+++ b/templates/show_params.mako
@@ -111,6 +111,7 @@
<tr><td>Filesize:</td><td>${nice_size(hda.dataset.file_size)}</td></tr><tr><td>Dbkey:</td><td>${hda.dbkey | h}</td></tr><tr><td>Format:</td><td>${hda.ext | h}</td></tr>
+ <tr><td>Galaxy Tool Version:</td><td>${job.tool_version | h}</td></tr><tr><td>Tool Version:</td><td>${hda.tool_version | h}</td></tr><tr><td>Tool Standard Output:</td><td><a href="${h.url_for( controller='dataset', action='stdout')}">stdout</a></td></tr><tr><td>Tool Standard Error:</td><td><a href="${h.url_for( controller='dataset', action='stderr')}">stderr</a></td></tr>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Change order of Bowtie2 output datasets to put aligned reads at top of history.
by Bitbucket 30 Jan '13
by Bitbucket 30 Jan '13
30 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/95e33df0ae03/
changeset: 95e33df0ae03
user: jgoecks
date: 2013-01-30 18:55:49
summary: Change order of Bowtie2 output datasets to put aligned reads at top of history.
affected #: 1 file
diff -r 6a03e7197bdc83512444d66bfd793e0c91596217 -r 95e33df0ae0332e04f14646abbf77c02672ef23a tools/sr_mapping/bowtie2_wrapper.xml
--- a/tools/sr_mapping/bowtie2_wrapper.xml
+++ b/tools/sr_mapping/bowtie2_wrapper.xml
@@ -145,6 +145,22 @@
</inputs><outputs>
+ <data format="fastqsanger" name="output_unaligned_reads_l" label="${tool.name} on ${on_string}: unaligned reads (L)" >
+ <filter>unalignedFile is True</filter>
+ <actions>
+ <action type="format">
+ <option type="from_param" name="singlePaired.input1" param_attribute="ext" />
+ </action>
+ </actions>
+ </data>
+ <data format="fastqsanger" name="output_unaligned_reads_r" label="${tool.name} on ${on_string}: unaligned reads (R)">
+ <filter>singlePaired['sPaired'] == "paired" and unalignedFile is True</filter>
+ <actions>
+ <action type="format">
+ <option type="from_param" name="singlePaired.input1" param_attribute="ext" />
+ </action>
+ </actions>
+ </data><data format="bam" name="output" label="${tool.name} on ${on_string}: aligned reads"><actions><conditional name="refGenomeSource.genomeSource">
@@ -164,22 +180,6 @@
</conditional></actions></data>
- <data format="fastqsanger" name="output_unaligned_reads_l" label="${tool.name} on ${on_string}: unaligned reads (L)" >
- <filter>unalignedFile is True</filter>
- <actions>
- <action type="format">
- <option type="from_param" name="singlePaired.input1" param_attribute="ext" />
- </action>
- </actions>
- </data>
- <data format="fastqsanger" name="output_unaligned_reads_r" label="${tool.name} on ${on_string}: unaligned reads (R)">
- <filter>singlePaired['sPaired'] == "paired" and unalignedFile is True</filter>
- <actions>
- <action type="format">
- <option type="from_param" name="singlePaired.input1" param_attribute="ext" />
- </action>
- </actions>
- </data></outputs><tests>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Collect and output comments when reading unordered GTF. Handle comments when converting from GTF to FLI.
by Bitbucket 30 Jan '13
by Bitbucket 30 Jan '13
30 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6a03e7197bdc/
changeset: 6a03e7197bdc
user: jgoecks
date: 2013-01-30 18:22:59
summary: Collect and output comments when reading unordered GTF. Handle comments when converting from GTF to FLI.
affected #: 2 files
diff -r f787a69139a284fe6c8fcaa52e506a6fa952c330 -r 6a03e7197bdc83512444d66bfd793e0c91596217 lib/galaxy/datatypes/converters/interval_to_fli.py
--- a/lib/galaxy/datatypes/converters/interval_to_fli.py
+++ b/lib/galaxy/datatypes/converters/interval_to_fli.py
@@ -16,6 +16,8 @@
import sys, optparse
from galaxy import eggs
+import pkg_resources; pkg_resources.require( "bx-python" )
+from bx.tabular.io import Comment
from galaxy.datatypes.util.gff_util import GFFReaderWrapper, read_unordered_gtf, convert_gff_coords_to_bed
def main():
@@ -38,6 +40,9 @@
in_reader = read_unordered_gtf( open( in_fname, 'r' ) )
for feature in in_reader:
+ if isinstance( feature, Comment ):
+ continue
+
for name in feature.attributes:
val = feature.attributes[ name ]
try:
diff -r f787a69139a284fe6c8fcaa52e506a6fa952c330 -r 6a03e7197bdc83512444d66bfd793e0c91596217 lib/galaxy/datatypes/util/gff_util.py
--- a/lib/galaxy/datatypes/util/gff_util.py
+++ b/lib/galaxy/datatypes/util/gff_util.py
@@ -384,9 +384,14 @@
key_fn = lambda fields: fields[0] + '_' + get_transcript_id( fields )
- # Aggregate intervals by transcript_id.
+ # Aggregate intervals by transcript_id and collect comments.
feature_intervals = odict()
+ comments = []
for count, line in enumerate( iterator ):
+ if line.startswith( '#' ):
+ comments.append( Comment( line ) )
+ continue
+
line_key = key_fn( line.split('\t') )
if line_key in feature_intervals:
feature = feature_intervals[ line_key ]
@@ -413,7 +418,13 @@
for features in chroms_features_sorted:
features.sort( lambda a,b: cmp( a.start, b.start ) )
- # Yield.
+ # Yield comments first, then features.
+ # FIXME: comments can appear anywhere in file, not just the beginning.
+ # Ideally, then comments would be associated with features and output
+ # just before feature/line.
+ for comment in comments:
+ yield comment
+
for chrom_features in chroms_features_sorted:
for feature in chrom_features:
yield feature
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
30 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f787a69139a2/
changeset: f787a69139a2
user: jgoecks
date: 2013-01-30 16:54:15
summary: Fixes for 149f0fc and pack scripts.
affected #: 3 files
diff -r f49ce2c1883e3e323deb86d11f9cde90b941bd58 -r f787a69139a284fe6c8fcaa52e506a6fa952c330 static/scripts/galaxy.grids.js
--- a/static/scripts/galaxy.grids.js
+++ b/static/scripts/galaxy.grids.js
@@ -119,11 +119,17 @@
async: this.attributes.async,
sort: this.attributes.sort_key,
page: this.attributes.cur_page,
- show_item_checkboxes: this.attributes.show_item_checkboxes,
- operation: this.attributes.operation,
- id: this.attributes.item_ids
+ show_item_checkboxes: this.attributes.show_item_checkboxes
};
+ // Add operation, item_ids only if they have values.
+ if (this.attributes.operation) {
+ url_data.operation = this.attributes.operation;
+ }
+ if (this.attributes.item_ids) {
+ url_data.id = this.attributes.item_ids;
+ }
+
// Add filter arguments to data, placing "f-" in front of all arguments.
// FIXME: when underscore updated, use pairs function().
var self = this;
@@ -476,6 +482,7 @@
// If grid is not using async, then go to URL.
if (!grid.get('async')) {
go_to_URL();
+ return;
}
// If there's an operation, do POST; otherwise, do GET.
diff -r f49ce2c1883e3e323deb86d11f9cde90b941bd58 -r f787a69139a284fe6c8fcaa52e506a6fa952c330 static/scripts/packed/galaxy.grids.js
--- a/static/scripts/packed/galaxy.grids.js
+++ b/static/scripts/packed/galaxy.grids.js
@@ -1,1 +1,1 @@
-jQuery.ajaxSettings.traditional=true;$(document).ready(function(){init_grid_elements();init_grid_controls();$("input[type=text]").each(function(){$(this).click(function(){$(this).select()}).keyup(function(){$(this).css("font-style","normal")})})});var Grid=Backbone.Model.extend({defaults:{url_base:"",async:false,async_ops:[],categorical_filters:[],filters:{},sort_key:null,show_item_checkboxes:false,cur_page:1,num_pages:1,operation:undefined,item_ids:undefined},can_async_op:function(a){return _.indexOf(this.attributes.async_ops,a)!==-1},add_filter:function(e,f,b){if(b){var c=this.attributes.key,a;if(c===null||c===undefined){a=f}else{if(typeof(c)=="string"){if(c=="All"){a=f}else{var d=[];d[0]=c;d[1]=f;a=d}}else{a=c;a.push(f)}}this.attributes.filters[e]=a}else{this.attributes.filters[e]=f}},remove_filter:function(b,e){var a=this.attributes.filters[b];if(a===null||a===undefined){return false}var d=true;if(typeof(a)==="string"){if(a=="All"){d=false}else{delete this.attributes.filters[b]}}else{var c=_.indexOf(a,e);if(c!==-1){a.splice(c,1)}else{d=false}}return d},get_url_data:function(){var a={async:this.attributes.async,sort:this.attributes.sort_key,page:this.attributes.cur_page,show_item_checkboxes:this.attributes.show_item_checkboxes,operation:this.attributes.operation,id:this.attributes.item_ids};var b=this;_.each(_.keys(b.attributes.filters),function(c){a["f-"+c]=b.attributes.filters[c]});return a}});function init_operation_buttons(){$("input[name=operation]:submit").each(function(){$(this).click(function(){var b=$(this).val();var a=[];$("input[name=id]:checked").each(function(){a.push($(this).val())});do_operation(b,a)})})}function init_grid_controls(){init_operation_buttons();$(".submit-image").each(function(){$(this).mousedown(function(){$(this).addClass("gray-background")});$(this).mouseup(function(){$(this).removeClass("gray-background")})});$(".sort-link").each(function(){$(this).click(function(){set_sort_condition($(this).attr("sort_key"));return false})});$(".page-link > a").each(function(){$(this).click(function(){set_page($(this).attr("page_num"));return false})});$(".categorical-filter > a").each(function(){$(this).click(function(){set_categorical_filter($(this).attr("filter_key"),$(this).attr("filter_val"));return false})});$(".text-filter-form").each(function(){$(this).submit(function(){var d=$(this).attr("column_key");var c=$("#input-"+d+"-filter");var e=c.val();c.val("");add_filter_condition(d,e,true);return false})});var a=$("#input-tags-filter");if(a.length){a.autocomplete(history_tag_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}var b=$("#input-name-filter");if(b.length){b.autocomplete(history_name_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}$(".advanced-search-toggle").each(function(){$(this).click(function(){$("#standard-search").slideToggle("fast");$("#advanced-search").slideToggle("fast");return false})})}function init_grid_elements(){$(".grid").each(function(){var b=$(this).find("input.grid-row-select-checkbox");var a=$(this).find("span.grid-selected-count");var c=function(){a.text($(b).filter(":checked").length)};$(b).each(function(){$(this).change(c)});c()});$(".label").each(function(){var a=$(this).attr("href");if(a!==undefined&&a.indexOf("operation=")!=-1){$(this).click(function(){do_operation_from_href($(this).attr("href"));return false})}});$(".community_rating_star").rating({});make_popup_menus()}function go_page_one(){var a=grid.get("cur_page");if(a!==null&&a!==undefined&&a!=="all"){grid.set("cur_page",1)}}function add_filter_condition(c,e,a){if(e===""){return false}grid.add_filter(c,e,a);var d=$("<span>"+e+"<a href='javascript:void(0);'><span class='delete-search-icon' /></a></span>");d.addClass("text-filter-val");d.click(function(){grid.remove_filter(c,e);$(this).remove();go_page_one();update_grid()});var b=$("#"+c+"-filtering-criteria");b.append(d);go_page_one();update_grid()}function add_tag_to_grid_filter(c,b){var a=c+(b!==undefined&&b!==""?":"+b:"");$("#advanced-search").show("fast");add_filter_condition("tags",a,true)}function set_sort_condition(f){var e=grid.get("sort_key");var d=f;if(e.indexOf(f)!==-1){if(e.substring(0,1)!=="-"){d="-"+f}else{}}$(".sort-arrow").remove();var c=(d.substring(0,1)=="-")?"↑":"↓";var a=$("<span>"+c+"</span>").addClass("sort-arrow");var b=$("#"+f+"-header");b.append(a);grid.set("sort_key",d);go_page_one();update_grid()}function set_categorical_filter(b,d){var a=grid.get("categorical_filters")[b],c=grid.get("filters")[b];$("."+b+"-filter").each(function(){var h=$.trim($(this).text());var f=a[h];var g=f[b];if(g==d){$(this).empty();$(this).addClass("current-filter");$(this).append(h)}else{if(g==c){$(this).empty();var e=$("<a href='#'>"+h+"</a>");e.click(function(){set_categorical_filter(b,g)});$(this).removeClass("current-filter");$(this).append(e)}}});grid.add_filter(b,d);go_page_one();update_grid()}function set_page(a){$(".page-link").each(function(){var g=$(this).attr("id"),e=parseInt(g.split("-")[2],10),c=grid.get("cur_page"),f;if(e===a){f=$(this).children().text();$(this).empty();$(this).addClass("inactive-link");$(this).text(f)}else{if(e===c){f=$(this).text();$(this).empty();$(this).removeClass("inactive-link");var d=$("<a href='#'>"+f+"</a>");d.click(function(){set_page(e)});$(this).append(d)}}});var b=true;if(a==="all"){grid.set("cur_page",a);b=false}else{grid.set("cur_page",parseInt(a,10))}update_grid(b)}function do_operation(b,a){b=b.toLowerCase();grid.set({operation:b,item_ids:a});if(grid.can_async_op(b)){update_grid(true)}else{go_to_URL()}}function do_operation_from_href(c){var f=c.split("?");if(f.length>1){var a=f[1];var e=a.split("&");var b=null;var g=-1;for(var d=0;d<e.length;d++){if(e[d].indexOf("operation")!=-1){b=e[d].split("=")[1]}else{if(e[d].indexOf("id")!=-1){g=e[d].split("=")[1]}}}do_operation(b,g);return false}}function go_to_URL(){grid.set("async",false);window.location=grid.get("url_base")+"?"+$.param(grid.get_url_data())}function update_grid(a){if(!grid.get("async")){go_to_URL()}var b=(grid.get("operation")?"POST":"GET");$(".loading-elt-overlay").show();$.ajax({type:b,url:grid.get("url_base"),data:grid.get_url_data(),error:function(){alert("Grid refresh failed")},success:function(d){var c=d.split("*****");$("#grid-table-body").html(c[0]);$("#grid-table-footer").html(c[1]);$("#grid-table-body").trigger("update");init_grid_elements();init_operation_buttons();make_popup_menus();$(".loading-elt-overlay").hide();var e=$.trim(c[2]);if(e!==""){$("#grid-message").html(e).show();setTimeout(function(){$("#grid-message").hide()},5000)}},complete:function(){grid.set({operation:undefined,item_ids:undefined})}})}function check_all_items(){var a=document.getElementById("check_all"),b=document.getElementsByTagName("input"),d=0,c;if(a.checked===true){for(c=0;c<b.length;c++){if(b[c].name.indexOf("id")!==-1){b[c].checked=true;d++}}}else{for(c=0;c<b.length;c++){if(b[c].name.indexOf("id")!==-1){b[c].checked=false}}}init_grid_elements()};
\ No newline at end of file
+jQuery.ajaxSettings.traditional=true;$(document).ready(function(){init_grid_elements();init_grid_controls();$("input[type=text]").each(function(){$(this).click(function(){$(this).select()}).keyup(function(){$(this).css("font-style","normal")})})});var Grid=Backbone.Model.extend({defaults:{url_base:"",async:false,async_ops:[],categorical_filters:[],filters:{},sort_key:null,show_item_checkboxes:false,cur_page:1,num_pages:1,operation:undefined,item_ids:undefined},can_async_op:function(a){return _.indexOf(this.attributes.async_ops,a)!==-1},add_filter:function(e,f,b){if(b){var c=this.attributes.key,a;if(c===null||c===undefined){a=f}else{if(typeof(c)=="string"){if(c=="All"){a=f}else{var d=[];d[0]=c;d[1]=f;a=d}}else{a=c;a.push(f)}}this.attributes.filters[e]=a}else{this.attributes.filters[e]=f}},remove_filter:function(b,e){var a=this.attributes.filters[b];if(a===null||a===undefined){return false}var d=true;if(typeof(a)==="string"){if(a=="All"){d=false}else{delete this.attributes.filters[b]}}else{var c=_.indexOf(a,e);if(c!==-1){a.splice(c,1)}else{d=false}}return d},get_url_data:function(){var a={async:this.attributes.async,sort:this.attributes.sort_key,page:this.attributes.cur_page,show_item_checkboxes:this.attributes.show_item_checkboxes};if(this.attributes.operation){a.operation=this.attributes.operation}if(this.attributes.item_ids){a.id=this.attributes.item_ids}var b=this;_.each(_.keys(b.attributes.filters),function(c){a["f-"+c]=b.attributes.filters[c]});return a}});function init_operation_buttons(){$("input[name=operation]:submit").each(function(){$(this).click(function(){var b=$(this).val();var a=[];$("input[name=id]:checked").each(function(){a.push($(this).val())});do_operation(b,a)})})}function init_grid_controls(){init_operation_buttons();$(".submit-image").each(function(){$(this).mousedown(function(){$(this).addClass("gray-background")});$(this).mouseup(function(){$(this).removeClass("gray-background")})});$(".sort-link").each(function(){$(this).click(function(){set_sort_condition($(this).attr("sort_key"));return false})});$(".page-link > a").each(function(){$(this).click(function(){set_page($(this).attr("page_num"));return false})});$(".categorical-filter > a").each(function(){$(this).click(function(){set_categorical_filter($(this).attr("filter_key"),$(this).attr("filter_val"));return false})});$(".text-filter-form").each(function(){$(this).submit(function(){var d=$(this).attr("column_key");var c=$("#input-"+d+"-filter");var e=c.val();c.val("");add_filter_condition(d,e,true);return false})});var a=$("#input-tags-filter");if(a.length){a.autocomplete(history_tag_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}var b=$("#input-name-filter");if(b.length){b.autocomplete(history_name_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}$(".advanced-search-toggle").each(function(){$(this).click(function(){$("#standard-search").slideToggle("fast");$("#advanced-search").slideToggle("fast");return false})})}function init_grid_elements(){$(".grid").each(function(){var b=$(this).find("input.grid-row-select-checkbox");var a=$(this).find("span.grid-selected-count");var c=function(){a.text($(b).filter(":checked").length)};$(b).each(function(){$(this).change(c)});c()});$(".label").each(function(){var a=$(this).attr("href");if(a!==undefined&&a.indexOf("operation=")!=-1){$(this).click(function(){do_operation_from_href($(this).attr("href"));return false})}});$(".community_rating_star").rating({});make_popup_menus()}function go_page_one(){var a=grid.get("cur_page");if(a!==null&&a!==undefined&&a!=="all"){grid.set("cur_page",1)}}function add_filter_condition(c,e,a){if(e===""){return false}grid.add_filter(c,e,a);var d=$("<span>"+e+"<a href='javascript:void(0);'><span class='delete-search-icon' /></a></span>");d.addClass("text-filter-val");d.click(function(){grid.remove_filter(c,e);$(this).remove();go_page_one();update_grid()});var b=$("#"+c+"-filtering-criteria");b.append(d);go_page_one();update_grid()}function add_tag_to_grid_filter(c,b){var a=c+(b!==undefined&&b!==""?":"+b:"");$("#advanced-search").show("fast");add_filter_condition("tags",a,true)}function set_sort_condition(f){var e=grid.get("sort_key");var d=f;if(e.indexOf(f)!==-1){if(e.substring(0,1)!=="-"){d="-"+f}else{}}$(".sort-arrow").remove();var c=(d.substring(0,1)=="-")?"↑":"↓";var a=$("<span>"+c+"</span>").addClass("sort-arrow");var b=$("#"+f+"-header");b.append(a);grid.set("sort_key",d);go_page_one();update_grid()}function set_categorical_filter(b,d){var a=grid.get("categorical_filters")[b],c=grid.get("filters")[b];$("."+b+"-filter").each(function(){var h=$.trim($(this).text());var f=a[h];var g=f[b];if(g==d){$(this).empty();$(this).addClass("current-filter");$(this).append(h)}else{if(g==c){$(this).empty();var e=$("<a href='#'>"+h+"</a>");e.click(function(){set_categorical_filter(b,g)});$(this).removeClass("current-filter");$(this).append(e)}}});grid.add_filter(b,d);go_page_one();update_grid()}function set_page(a){$(".page-link").each(function(){var g=$(this).attr("id"),e=parseInt(g.split("-")[2],10),c=grid.get("cur_page"),f;if(e===a){f=$(this).children().text();$(this).empty();$(this).addClass("inactive-link");$(this).text(f)}else{if(e===c){f=$(this).text();$(this).empty();$(this).removeClass("inactive-link");var d=$("<a href='#'>"+f+"</a>");d.click(function(){set_page(e)});$(this).append(d)}}});var b=true;if(a==="all"){grid.set("cur_page",a);b=false}else{grid.set("cur_page",parseInt(a,10))}update_grid(b)}function do_operation(b,a){b=b.toLowerCase();grid.set({operation:b,item_ids:a});if(grid.can_async_op(b)){update_grid(true)}else{go_to_URL()}}function do_operation_from_href(c){var f=c.split("?");if(f.length>1){var a=f[1];var e=a.split("&");var b=null;var g=-1;for(var d=0;d<e.length;d++){if(e[d].indexOf("operation")!=-1){b=e[d].split("=")[1]}else{if(e[d].indexOf("id")!=-1){g=e[d].split("=")[1]}}}do_operation(b,g);return false}}function go_to_URL(){grid.set("async",false);window.location=grid.get("url_base")+"?"+$.param(grid.get_url_data())}function update_grid(a){if(!grid.get("async")){go_to_URL();return}var b=(grid.get("operation")?"POST":"GET");$(".loading-elt-overlay").show();$.ajax({type:b,url:grid.get("url_base"),data:grid.get_url_data(),error:function(){alert("Grid refresh failed")},success:function(d){var c=d.split("*****");$("#grid-table-body").html(c[0]);$("#grid-table-footer").html(c[1]);$("#grid-table-body").trigger("update");init_grid_elements();init_operation_buttons();make_popup_menus();$(".loading-elt-overlay").hide();var e=$.trim(c[2]);if(e!==""){$("#grid-message").html(e).show();setTimeout(function(){$("#grid-message").hide()},5000)}},complete:function(){grid.set({operation:undefined,item_ids:undefined})}})}function check_all_items(){var a=document.getElementById("check_all"),b=document.getElementsByTagName("input"),d=0,c;if(a.checked===true){for(c=0;c<b.length;c++){if(b[c].name.indexOf("id")!==-1){b[c].checked=true;d++}}}else{for(c=0;c<b.length;c++){if(b[c].name.indexOf("id")!==-1){b[c].checked=false}}}init_grid_elements()};
\ No newline at end of file
diff -r f49ce2c1883e3e323deb86d11f9cde90b941bd58 -r f787a69139a284fe6c8fcaa52e506a6fa952c330 static/scripts/packed/mvc/data.js
--- a/static/scripts/packed/mvc/data.js
+++ b/static/scripts/packed/mvc/data.js
@@ -1,1 +1,1 @@
-define(["libs/backbone/backbone-relational"],function(){var a=Backbone.RelationalModel.extend({defaults:{id:"",type:"",name:"",hda_ldda:"hda"},urlRoot:galaxy_paths.get("datasets_url")});var b=Backbone.Collection.extend({model:a});return{Dataset:a,DatasetCollection:b}});
\ No newline at end of file
+define(["libs/backbone/backbone-relational"],function(){var a=Backbone.RelationalModel.extend({});var b=Backbone.RelationalModel.extend({defaults:{id:"",type:"",name:"",hda_ldda:"hda",metadata:null},initialize:function(){var d=new a();_.each(_.keys(this.attributes),function(e){if(e.indexOf("metadata_")===0){var f=e.split("metadata_")[1];d.set(f,this.attributes[e]);delete this.attributes[e]}},this);this.set("metadata",d)},get_metadata:function(d){return this.attributes.metadata.get(d)},urlRoot:galaxy_paths.get("datasets_url")});var c=Backbone.Collection.extend({model:b});return{Dataset:b,DatasetCollection:c}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Add missing output file for new trimmer test.
by Bitbucket 30 Jan '13
by Bitbucket 30 Jan '13
30 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f49ce2c1883e/
changeset: f49ce2c1883e
user: jgoecks
date: 2013-01-30 15:03:27
summary: Add missing output file for new trimmer test.
affected #: 1 file
diff -r 2a43d292c0977e0fe82088ac106c119ffd866baa -r f49ce2c1883e3e323deb86d11f9cde90b941bd58 test-data/trimmer_a_f_c2_s2_e-2_i62.dat
--- /dev/null
+++ b/test-data/trimmer_a_f_c2_s2_e-2_i62.dat
@@ -0,0 +1,5 @@
+12345 bcd xyz
+67890 hj ghjt
+>assa lljlj ljlj
+sasas g hghg
+@dgf f gfgf
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: joachimjacob: Adjusted trimming tool to include negative positions. Modified help and test.
by Bitbucket 30 Jan '13
by Bitbucket 30 Jan '13
30 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2a43d292c097/
changeset: 2a43d292c097
user: joachimjacob
date: 2013-01-30 10:38:58
summary: Adjusted trimming tool to include negative positions. Modified help and test.
affected #: 2 files
diff -r 301d7447dd22fcfcbd7c4f5c5737fd0fdc82690b -r 2a43d292c0977e0fe82088ac106c119ffd866baa tools/filters/trimmer.py
--- a/tools/filters/trimmer.py
+++ b/tools/filters/trimmer.py
@@ -88,6 +88,9 @@
if col == 0:
if int( options.end ) > 0:
line = line[ int( options.start )-1 : int( options.end ) ]
+ elif int( options.end ) < 0:
+ endposition = len(line)+int( options.end )
+ line = line[ int( options.start )-1 : endposition ]
else:
line = line[ int( options.start )-1 : ]
else:
@@ -97,6 +100,9 @@
if int( options.end ) > 0:
fields[col - 1] = fields[col - 1][ int( options.start )-1 : int( options.end ) ]
+ elif int( options.end ) < 0:
+ endposition = len(fields[col - 1])+int( options.end )
+ fields[col - 1] = fields[col - 1][ int( options.start )-1 : endposition ]
else:
fields[col - 1] = fields[col - 1][ int( options.start )-1 : ]
line = '\t'.join(fields)
diff -r 301d7447dd22fcfcbd7c4f5c5737fd0fdc82690b -r 2a43d292c0977e0fe82088ac106c119ffd866baa tools/filters/trimmer.xml
--- a/tools/filters/trimmer.xml
+++ b/tools/filters/trimmer.xml
@@ -6,9 +6,9 @@
<inputs><param format="tabular,txt" name="input1" type="data" label="this dataset"/><param name="col" type="integer" value="0" label="Trim this column only" help="0 = process entire line" />
- <param name="start" type="integer" size="10" value="1" label="Trim from the beginning to this position" help="1 = do not trim the beginning"/>
- <param name="end" type="integer" size="10" value="0" label="Remove everything from this position to the end" help="0 = do not trim the end"/>
- <param name="fastq" type="select" label="Is input dataset in fastq format?" help="If set to YES, the tool will not trim evenly numbered lines (0, 2, 4, etc...)">
+ <param name="start" type="integer" size="10" value="1" label="Trim from the beginning up to this position" help="Only positive positions allowed. 1 = do not trim the beginning"/>
+ <param name="end" type="integer" size="10" value="0" label="Remove everything from this position to the end" help="Use negative position to indicate position starting from the end. 0 = do not trim the end"/>
+ <param name="fastq" type="select" label="Is input dataset in fastq format?" help="If set to YES, the tool will not trim evenly numbered lines (0, 2, 4, etc...). This allows for trimming the seq and qual lines, only if they are not spread over multiple lines (see warning below)."><option selected="true" value="">No</option><option value="-q">Yes</option></param>
@@ -53,7 +53,15 @@
<param name="fastq" value="No"/><output name="out_file1" file="trimmer_a_f_c2_s1_e2_i62.dat"/></test>
-
+ <test>
+ <param name="input1" value="trimmer_tab_delimited.dat"/>
+ <param name="col" value="2"/>
+ <param name="start" value="2"/>
+ <param name="end" value="-2"/>
+ <param name="ignore" value="62"/>
+ <param name="fastq" value="No"/>
+ <output name="out_file1" file="trimmer_a_f_c2_s2_e-2_i62.dat"/>
+ </test></tests><help>
@@ -72,7 +80,7 @@
1234567890
abcdefghijk
-by setting **Trim from the beginning to this position** to *2* and **Remove everything from this position to the end** to *6* will produce::
+by setting **Trim from the beginning up to this position** to *2* and **Remove everything from this position to the end** to *6* will produce::
23456
bcdef
@@ -86,13 +94,27 @@
abcde 12345 fghij 67890
fghij 67890 abcde 12345
-by setting **Trim content of this column only** to *2*, **Trim from the beginning to this position** to *2*, and **Remove everything from this position to the end** to *4* will produce::
+by setting **Trim content of this column only** to *2*, **Trim from the beginning up to this position** to *2*, and **Remove everything from this position to the end** to *4* will produce::
abcde 234 fghij 67890
fghij 789 abcde 12345
-----
+**Example 3**
+
+Trimming column 2 of this dataset::
+
+ abcde 12345 fghij 67890
+ fghij 67890 abcde 12345
+
+by setting **Trim content of this column only** to *2*, **Trim from the beginning up to this position** to *2*, and **Remove everything from this position to the end** to *-2* will produce::
+
+ abcde 23 fghij 67890
+ fghij 78 abcde 12345
+
+----
+
**Trimming FASTQ datasets**
This tool can be used to trim sequences and quality strings in fastq datasets. This is done by selected *Yes* from the **Is input dataset in fastq format?** dropdown. If set to *Yes*, the tool will skip all even numbered lines (see warning below). For example, trimming last 5 bases of this dataset::
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
6 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/96dd7b391ae4/
changeset: 96dd7b391ae4
user: jmchilton
date: 2012-10-19 06:32:32
summary: Improved encapsulation of job splitting logic, setting the stage for implicit splitting.
affected #: 2 files
diff -r 340438c62171578078323d39da398d5053b69d0a -r 96dd7b391ae478e82af14153495d61225bf55dcd lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -89,6 +89,10 @@
self.__user_system_pwent = None
self.__galaxy_system_pwent = None
+ def can_split( self ):
+ # Should the job handler split this job up?
+ return self.app.config.use_tasked_jobs and self.tool.parallelism
+
def get_job_runner_url( self ):
return self.job_runner_mapper.get_job_runner_url( self.params )
@@ -922,6 +926,11 @@
self.prepare_input_files_cmds = None
self.status = task.states.NEW
+ def can_split( self ):
+ # Should the job handler split this job up? TaskWrapper should
+ # always return False as the job has already been split.
+ return False
+
def get_job( self ):
if self.job_id:
return self.sa_session.query( model.Job ).get( self.job_id )
diff -r 340438c62171578078323d39da398d5053b69d0a -r 96dd7b391ae478e82af14153495d61225bf55dcd lib/galaxy/jobs/handler.py
--- a/lib/galaxy/jobs/handler.py
+++ b/lib/galaxy/jobs/handler.py
@@ -449,7 +449,7 @@
log.debug( 'Loaded job runner: %s' % display_name )
def __get_runner_name( self, job_wrapper ):
- if self.app.config.use_tasked_jobs and job_wrapper.tool.parallelism is not None and not isinstance(job_wrapper, TaskWrapper):
+ if job_wrapper.can_split():
runner_name = "tasks"
else:
runner_name = ( job_wrapper.get_job_runner_url().split(":", 1) )[0]
@@ -458,7 +458,7 @@
def put( self, job_wrapper ):
try:
runner_name = self.__get_runner_name( job_wrapper )
- if self.app.config.use_tasked_jobs and job_wrapper.tool.parallelism is not None and isinstance(job_wrapper, TaskWrapper):
+ if isinstance(job_wrapper, TaskWrapper):
#DBTODO Refactor
log.debug( "dispatching task %s, of job %d, to %s runner" %( job_wrapper.task_id, job_wrapper.job_id, runner_name ) )
else:
https://bitbucket.org/galaxy/galaxy-central/commits/4bafc5e59111/
changeset: 4bafc5e59111
user: jmchilton
date: 2012-11-11 22:36:14
summary: Replace access pattern 'job_wrapper.tool.parallelism' with 'job_wrapper.get_parallelism()' (a newly implemented method on JobWrapper) as a step toward enabling of per job parallelism (as opposed to per tool parallelism).
affected #: 4 files
diff -r 96dd7b391ae478e82af14153495d61225bf55dcd -r 4bafc5e59111cc2b8e374d2ab816a5c12d4ed459 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -96,6 +96,9 @@
def get_job_runner_url( self ):
return self.job_runner_mapper.get_job_runner_url( self.params )
+ def get_parallelism(self):
+ return self.tool.parallelism
+
# legacy naming
get_job_runner = get_job_runner_url
diff -r 96dd7b391ae478e82af14153495d61225bf55dcd -r 4bafc5e59111cc2b8e374d2ab816a5c12d4ed459 lib/galaxy/jobs/runners/tasks.py
--- a/lib/galaxy/jobs/runners/tasks.py
+++ b/lib/galaxy/jobs/runners/tasks.py
@@ -71,12 +71,13 @@
try:
job_wrapper.change_state( model.Job.states.RUNNING )
self.sa_session.flush()
- # Split with the tool-defined method.
+ # Split with the defined method.
+ parallelism = job_wrapper.get_parallelism()
try:
- splitter = getattr(__import__('galaxy.jobs.splitters', globals(), locals(), [job_wrapper.tool.parallelism.method]), job_wrapper.tool.parallelism.method)
+ splitter = getattr(__import__('galaxy.jobs.splitters', globals(), locals(), [parallelism.method]), parallelism.method)
except:
job_wrapper.change_state( model.Job.states.ERROR )
- job_wrapper.fail("Job Splitting Failed, no match for '%s'" % job_wrapper.tool.parallelism)
+ job_wrapper.fail("Job Splitting Failed, no match for '%s'" % parallelism)
return
tasks = splitter.do_split(job_wrapper)
# Not an option for now. Task objects don't *do* anything
diff -r 96dd7b391ae478e82af14153495d61225bf55dcd -r 4bafc5e59111cc2b8e374d2ab816a5c12d4ed459 lib/galaxy/jobs/splitters/basic.py
--- a/lib/galaxy/jobs/splitters/basic.py
+++ b/lib/galaxy/jobs/splitters/basic.py
@@ -5,8 +5,9 @@
def set_basic_defaults(job_wrapper):
parent_job = job_wrapper.get_job()
- job_wrapper.tool.parallelism.attributes['split_inputs'] = parent_job.input_datasets[0].name
- job_wrapper.tool.parallelism.attributes['merge_outputs'] = job_wrapper.get_output_hdas_and_fnames().keys()[0]
+ parallelism = job_wrapper.get_parallelism()
+ parallelism.attributes['split_inputs'] = parent_job.input_datasets[0].name
+ parallelism.attributes['merge_outputs'] = job_wrapper.get_output_hdas_and_fnames().keys()[0]
def do_split (job_wrapper):
if len(job_wrapper.get_input_fnames()) > 1 or len(job_wrapper.get_output_fnames()) > 1:
diff -r 96dd7b391ae478e82af14153495d61225bf55dcd -r 4bafc5e59111cc2b8e374d2ab816a5c12d4ed459 lib/galaxy/jobs/splitters/multi.py
--- a/lib/galaxy/jobs/splitters/multi.py
+++ b/lib/galaxy/jobs/splitters/multi.py
@@ -8,7 +8,7 @@
parent_job = job_wrapper.get_job()
working_directory = os.path.abspath(job_wrapper.working_directory)
- parallel_settings = job_wrapper.tool.parallelism.attributes
+ parallel_settings = job_wrapper.get_parallelism().attributes
# Syntax: split_inputs="input1,input2" shared_inputs="genome"
# Designates inputs to be split or shared
split_inputs=parallel_settings.get("split_inputs")
@@ -91,7 +91,7 @@
def do_merge( job_wrapper, task_wrappers):
- parallel_settings = job_wrapper.tool.parallelism.attributes
+ parallel_settings = job_wrapper.get_parallelism().attributes
# Syntax: merge_outputs="export" pickone_outputs="genomesize"
# Designates outputs to be merged, or selected from as a representative
merge_outputs = parallel_settings.get("merge_outputs")
https://bitbucket.org/galaxy/galaxy-central/commits/53d3d620a878/
changeset: 53d3d620a878
user: jmchilton
date: 2012-11-15 16:19:08
summary: Rename ToolParallelismInfo to ParallelismInfo and move to jobs module to reflect the fact per-job (instead of per-tool) parallelism could also be a possibility (even if only in downstream Galaxy forks). Also, allow building these objects from dictionaries (in addition to traditional XML-based creation).
affected #: 2 files
diff -r 4bafc5e59111cc2b8e374d2ab816a5c12d4ed459 -r 53d3d620a8783a7ac4de9360e3691853681ffac3 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -1153,3 +1153,20 @@
return
def shutdown( self ):
return
+
+class ParallelismInfo(object):
+ """
+ Stores the information (if any) for running multiple instances of the tool in parallel
+ on the same set of inputs.
+ """
+ def __init__(self, tag):
+ self.method = tag.get('method')
+ if isinstance(tag, dict):
+ items = tag.iteritems()
+ else:
+ items = tag.attrib.items()
+ self.attributes = dict([item for item in items if item[0] != 'method' ])
+ if len(self.attributes) == 0:
+ # legacy basic mode - provide compatible defaults
+ self.attributes['split_size'] = 20
+ self.attributes['split_mode'] = 'number_of_parts'
diff -r 4bafc5e59111cc2b8e374d2ab816a5c12d4ed459 -r 53d3d620a8783a7ac4de9360e3691853681ffac3 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -15,6 +15,7 @@
from galaxy.util.bunch import Bunch
from galaxy.util.template import fill_template
from galaxy import util, jobs, model
+from galaxy.jobs import ParallelismInfo
from elementtree import ElementTree
from parameters import *
from parameters.grouping import *
@@ -797,19 +798,6 @@
self.type = type
self.version = version
-class ToolParallelismInfo(object):
- """
- Stores the information (if any) for running multiple instances of the tool in parallel
- on the same set of inputs.
- """
- def __init__(self, tag):
- self.method = tag.get('method')
- self.attributes = dict([item for item in tag.attrib.items() if item[0] != 'method' ])
- if len(self.attributes) == 0:
- # legacy basic mode - provide compatible defaults
- self.attributes['split_size'] = 20
- self.attributes['split_mode'] = 'number_of_parts'
-
class Tool:
"""
Represents a computational tool that can be executed through Galaxy.
@@ -989,7 +977,7 @@
# Parallelism for tasks, read from tool config.
parallelism = root.find("parallelism")
if parallelism is not None and parallelism.get("method"):
- self.parallelism = ToolParallelismInfo(parallelism)
+ self.parallelism = ParallelismInfo(parallelism)
else:
self.parallelism = None
# Set job handler(s). Each handler is a dict with 'url' and, optionally, 'params'.
https://bitbucket.org/galaxy/galaxy-central/commits/e67fb0786e41/
changeset: e67fb0786e41
user: jmchilton
date: 2012-11-26 19:55:15
summary: Merge with latest galaxy-central and resolve conflict introduced with pull request 82 was accepted.
affected #: 154 files
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 README.txt
--- a/README.txt
+++ b/README.txt
@@ -10,7 +10,7 @@
Galaxy requires Python 2.5, 2.6 or 2.7. To check your python version, run:
% python -V
-Python 2.4.4
+Python 2.7.3
Start Galaxy:
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/datatypes/assembly.py
--- a/lib/galaxy/datatypes/assembly.py
+++ b/lib/galaxy/datatypes/assembly.py
@@ -225,4 +225,3 @@
if __name__ == '__main__':
import doctest, sys
doctest.testmod(sys.modules[__name__])
-
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/datatypes/data.py
--- a/lib/galaxy/datatypes/data.py
+++ b/lib/galaxy/datatypes/data.py
@@ -69,6 +69,9 @@
<class 'galaxy.datatypes.metadata.MetadataParameter'>
"""
+ #: dictionary of metadata fields for this datatype::
+ metadata_spec = None
+
__metaclass__ = DataMeta
# Add metadata elements
MetadataElement( name="dbkey", desc="Database/Build", default="?", param=metadata.DBKeyParameter, multiple=False, no_value="?" )
@@ -849,4 +852,3 @@
except UnicodeDecodeError:
text = "binary/unknown file"
return text
-
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -123,6 +123,7 @@
def __getstate__( self ):
return None #cannot pickle a weakref item (self._parent), when data._metadata_collection is None, it will be recreated on demand
+
class MetadataSpecCollection( odict ):
"""
A simple extension of dict which allows cleaner access to items
@@ -132,13 +133,21 @@
"""
def __init__( self, dict = None ):
odict.__init__( self, dict = None )
+
def append( self, item ):
self[item.name] = item
+
def iter( self ):
return self.itervalues()
+
def __getattr__( self, name ):
return self.get( name )
+ def __repr__( self ):
+ # force elements to draw with __str__ for sphinx-apidoc
+ return ', '.join([ item.__str__() for item in self.iter() ])
+
+
class MetadataParameter( object ):
def __init__( self, spec ):
self.spec = spec
@@ -185,7 +194,6 @@
"""
pass
-
def unwrap( self, form_value ):
"""
Turns a value into its storable form.
@@ -205,19 +213,22 @@
Turns a value read from an external dict into its value to be pushed directly into the metadata dict.
"""
return value
+
def to_external_value( self, value ):
"""
Turns a value read from a metadata into its value to be pushed directly into the external dict.
"""
return value
+
class MetadataElementSpec( object ):
"""
Defines a metadata element and adds it to the metadata_spec (which
is a MetadataSpecCollection) of datatype.
"""
-
- def __init__( self, datatype, name=None, desc=None, param=MetadataParameter, default=None, no_value = None, visible=True, set_in_upload = False, **kwargs ):
+ def __init__( self, datatype,
+ name=None, desc=None, param=MetadataParameter, default=None, no_value = None,
+ visible=True, set_in_upload = False, **kwargs ):
self.name = name
self.desc = desc or name
self.default = default
@@ -226,24 +237,37 @@
self.set_in_upload = set_in_upload
# Catch-all, allows for extra attributes to be set
self.__dict__.update(kwargs)
- #set up param last, as it uses values set above
+ # set up param last, as it uses values set above
self.param = param( self )
- datatype.metadata_spec.append( self ) #add spec element to the spec
+ # add spec element to the spec
+ datatype.metadata_spec.append( self )
+
def get( self, name, default=None ):
return self.__dict__.get(name, default)
+
def wrap( self, value ):
"""
Turns a stored value into its usable form.
"""
return self.param.wrap( value )
+
def unwrap( self, value ):
"""
Turns an incoming value into its storable form.
"""
return self.param.unwrap( value )
+ def __str__( self ):
+ #TODO??: assuming param is the class of this MetadataElementSpec - add the plain class name for that
+ spec_dict = dict( param_class=self.param.__class__.__name__ )
+ spec_dict.update( self.__dict__ )
+ return ( "{name} ({param_class}): {desc}, defaults to '{default}'".format( **spec_dict ) )
+
+# create a statement class that, when called,
+# will add a new MetadataElementSpec to a class's metadata_spec
MetadataElement = Statement( MetadataElementSpec )
+
"""
MetadataParameter sub-classes.
"""
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -252,6 +252,9 @@
# Update (non-library) job output datasets through the object store
if dataset not in job.output_library_datasets:
self.app.object_store.update_from_file(dataset.dataset, create=True)
+ # Pause any dependent jobs (and those jobs' outputs)
+ for dep_job_assoc in dataset.dependent_jobs:
+ self.pause( dep_job_assoc.job, "Execution of this dataset's job is paused because its input datasets are in an error state." )
self.sa_session.add( dataset )
self.sa_session.flush()
job.state = job.states.ERROR
@@ -282,6 +285,19 @@
if self.app.config.cleanup_job == 'always' or (self.app.config.cleanup_job == 'onsuccess' and job.state == job.states.DELETED):
self.cleanup()
+ def pause( self, job=None, message=None ):
+ if job is None:
+ job = self.get_job()
+ if message is None:
+ message = "Execution of this dataset's job is paused"
+ if job.state == job.states.NEW:
+ for dataset_assoc in job.output_datasets + job.output_library_datasets:
+ dataset_assoc.dataset.dataset.state = dataset_assoc.dataset.dataset.states.PAUSED
+ dataset_assoc.dataset.info = message
+ self.sa_session.add( dataset_assoc.dataset )
+ job.state = job.states.PAUSED
+ self.sa_session.add( job )
+
def change_state( self, state, info = False ):
job = self.get_job()
self.sa_session.refresh( job )
@@ -444,6 +460,9 @@
log.debug( "setting dataset state to ERROR" )
# TODO: This is where the state is being set to error. Change it!
dataset_assoc.dataset.dataset.state = model.Dataset.states.ERROR
+ # Pause any dependent jobs (and those jobs' outputs)
+ for dep_job_assoc in dataset_assoc.dataset.dependent_jobs:
+ self.pause( dep_job_assoc.job, "Execution of this dataset's job is paused because its input datasets are in an error state." )
else:
dataset_assoc.dataset.dataset.state = model.Dataset.states.OK
# If any of the rest of the finish method below raises an
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/jobs/handler.py
--- a/lib/galaxy/jobs/handler.py
+++ b/lib/galaxy/jobs/handler.py
@@ -17,6 +17,7 @@
# States for running a job. These are NOT the same as data states
JOB_WAIT, JOB_ERROR, JOB_INPUT_ERROR, JOB_INPUT_DELETED, JOB_READY, JOB_DELETED, JOB_ADMIN_DELETED, JOB_USER_OVER_QUOTA = 'wait', 'error', 'input_error', 'input_deleted', 'ready', 'deleted', 'admin_deleted', 'user_over_quota'
+DEFAULT_JOB_PUT_FAILURE_MESSAGE = 'Unable to run job due to a misconfiguration of the Galaxy job running system. Please contact a site administrator.'
class JobHandler( object ):
"""
@@ -41,6 +42,7 @@
a JobRunner.
"""
STOP_SIGNAL = object()
+
def __init__( self, app, dispatcher ):
"""Start the job manager"""
self.app = app
@@ -193,6 +195,10 @@
elif job_state == JOB_USER_OVER_QUOTA:
log.info( "(%d) User (%s) is over quota: job paused" % ( job.id, job.user_id ) )
job.state = model.Job.states.PAUSED
+ for dataset_assoc in job.output_datasets + job.output_library_datasets:
+ dataset_assoc.dataset.dataset.state = model.Dataset.states.PAUSED
+ dataset_assoc.dataset.info = "Execution of this dataset's job is paused because you were over your disk quota at the time it was ready to run"
+ self.sa_session.add( dataset_assoc.dataset.dataset )
self.sa_session.add( job )
else:
log.error( "(%d) Job in unknown state '%s'" % ( job.id, job_state ) )
@@ -458,6 +464,15 @@
def put( self, job_wrapper ):
try:
runner_name = self.__get_runner_name( job_wrapper )
+ except Exception, e:
+ failure_message = getattr(e, 'failure_message', DEFAULT_JOB_PUT_FAILURE_MESSAGE )
+ if failure_message == DEFAULT_JOB_PUT_FAILURE_MESSAGE:
+ log.exception( 'Failed to generate job runner name' )
+ else:
+ log.debug( "Intentionally failing job with message (%s)" % failure_message )
+ job_wrapper.fail( failure_message )
+ return
+ try:
if isinstance(job_wrapper, TaskWrapper):
#DBTODO Refactor
log.debug( "dispatching task %s, of job %d, to %s runner" %( job_wrapper.task_id, job_wrapper.job_id, runner_name ) )
@@ -466,7 +481,7 @@
self.job_runners[runner_name].put( job_wrapper )
except KeyError:
log.error( 'put(): (%s) Invalid job runner: %s' % ( job_wrapper.job_id, runner_name ) )
- job_wrapper.fail( 'Unable to run job due to a misconfiguration of the Galaxy job running system. Please contact a site administrator.' )
+ job_wrapper.fail( DEFAULT_JOB_PUT_FAILURE_MESSAGE )
def stop( self, job ):
"""
@@ -508,7 +523,7 @@
self.job_runners[runner_name].recover( job, job_wrapper )
except KeyError:
log.error( 'recover(): (%s) Invalid job runner: %s' % ( job_wrapper.job_id, runner_name ) )
- job_wrapper.fail( 'Unable to run job due to a misconfiguration of the Galaxy job running system. Please contact a site administrator.' )
+ job_wrapper.fail( DEFAULT_JOB_PUT_FAILURE_MESSAGE )
def shutdown( self ):
for runner in self.job_runners.itervalues():
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/jobs/mapper.py
--- a/lib/galaxy/jobs/mapper.py
+++ b/lib/galaxy/jobs/mapper.py
@@ -8,6 +8,12 @@
DYNAMIC_RUNNER_PREFIX = "dynamic:///"
+class JobMappingException( Exception ):
+
+ def __init__( self, failure_message ):
+ self.failure_message = failure_message
+
+
class JobRunnerMapper( object ):
"""
This class is responsible to managing the mapping of jobs
@@ -116,7 +122,7 @@
def __cache_job_runner_url( self, params ):
# If there's already a runner set in the Job object, don't overwrite from the tool
- if self.job_runner_name is not None:
+ if self.job_runner_name is not None and not self.job_runner_name.startswith('tasks'):
raw_job_runner_url = self.job_runner_name
else:
raw_job_runner_url = self.job_wrapper.tool.get_job_runner_url( params )
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/jobs/runners/cli.py
--- a/lib/galaxy/jobs/runners/cli.py
+++ b/lib/galaxy/jobs/runners/cli.py
@@ -359,12 +359,16 @@
def recover( self, job, job_wrapper ):
"""Recovers jobs stuck in the queued/running state when Galaxy started"""
+ job_id = job.get_job_runner_external_id()
+ if job_id is None:
+ self.put( job_wrapper )
+ return
runner_job_state = RunnerJobState()
runner_job_state.ofile = "%s.gjout" % os.path.join(job_wrapper.working_directory, job_wrapper.get_id_tag())
runner_job_state.efile = "%s.gjerr" % os.path.join(job_wrapper.working_directory, job_wrapper.get_id_tag())
runner_job_state.ecfile = "%s.gjec" % os.path.join(job_wrapper.working_directory, job_wrapper.get_id_tag())
runner_job_state.job_file = "%s/galaxy_%s.sh" % (self.app.config.cluster_files_directory, job_wrapper.get_id_tag())
- runner_job_state.external_job_id = str( job.job_runner_external_id )
+ runner_job_state.external_job_id = str( job_id )
job_wrapper.command_line = job.command_line
runner_job_state.job_wrapper = job_wrapper
runner_job_state.runner_url = job.job_runner_name
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/jobs/runners/condor.py
--- a/lib/galaxy/jobs/runners/condor.py
+++ b/lib/galaxy/jobs/runners/condor.py
@@ -368,11 +368,15 @@
def recover( self, job, job_wrapper ):
"""Recovers jobs stuck in the queued/running state when Galaxy started"""
# TODO Check if we need any changes here
+ job_id = job.get_job_runner_external_id()
+ if job_id is None:
+ self.put( job_wrapper )
+ return
drm_job_state = CondorJobState()
drm_job_state.ofile = "%s/database/pbs/%s.o" % (os.getcwd(), job.id)
drm_job_state.efile = "%s/database/pbs/%s.e" % (os.getcwd(), job.id)
drm_job_state.job_file = "%s/database/pbs/galaxy_%s.sh" % (os.getcwd(), job.id)
- drm_job_state.job_id = str( job.job_runner_external_id )
+ drm_job_state.job_id = str( job_id )
drm_job_state.runner_url = job_wrapper.get_job_runner()
job_wrapper.command_line = job.command_line
drm_job_state.job_wrapper = job_wrapper
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/jobs/runners/drmaa.py
--- a/lib/galaxy/jobs/runners/drmaa.py
+++ b/lib/galaxy/jobs/runners/drmaa.py
@@ -411,12 +411,16 @@
def recover( self, job, job_wrapper ):
"""Recovers jobs stuck in the queued/running state when Galaxy started"""
+ job_id = job.get_job_runner_external_id()
+ if job_id is None:
+ self.put( job_wrapper )
+ return
drm_job_state = DRMAAJobState()
drm_job_state.ofile = "%s.drmout" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
drm_job_state.efile = "%s.drmerr" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
drm_job_state.ecfile = "%s.drmec" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
drm_job_state.job_file = "%s/galaxy_%s.sh" % (self.app.config.cluster_files_directory, job.get_id())
- drm_job_state.job_id = str( job.get_job_runner_external_id() )
+ drm_job_state.job_id = str( job_id )
drm_job_state.runner_url = job_wrapper.get_job_runner_url()
job_wrapper.command_line = job.get_command_line()
drm_job_state.job_wrapper = job_wrapper
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/jobs/runners/pbs.py
--- a/lib/galaxy/jobs/runners/pbs.py
+++ b/lib/galaxy/jobs/runners/pbs.py
@@ -640,12 +640,16 @@
def recover( self, job, job_wrapper ):
"""Recovers jobs stuck in the queued/running state when Galaxy started"""
+ job_id = job.get_job_runner_external_id()
+ if job_id is None:
+ self.put( job_wrapper )
+ return
pbs_job_state = PBSJobState()
pbs_job_state.ofile = "%s/%s.o" % (self.app.config.cluster_files_directory, job.id)
pbs_job_state.efile = "%s/%s.e" % (self.app.config.cluster_files_directory, job.id)
pbs_job_state.ecfile = "%s/%s.ec" % (self.app.config.cluster_files_directory, job.id)
pbs_job_state.job_file = "%s/%s.sh" % (self.app.config.cluster_files_directory, job.id)
- pbs_job_state.job_id = str( job.get_job_runner_external_id() )
+ pbs_job_state.job_id = str( job_id )
pbs_job_state.runner_url = job_wrapper.get_job_runner_url()
job_wrapper.command_line = job.command_line
pbs_job_state.job_wrapper = job_wrapper
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/jobs/runners/sge.py
--- a/lib/galaxy/jobs/runners/sge.py
+++ /dev/null
@@ -1,392 +0,0 @@
-import os, logging, threading, time
-from Queue import Queue, Empty
-
-from galaxy import model
-from galaxy.jobs.runners import BaseJobRunner
-
-from paste.deploy.converters import asbool
-
-import pkg_resources
-
-egg_message = """
-
-The 'sge' runner depends on 'DRMAA_python' which is not installed. Galaxy's
-"scramble" system should make this installation simple, please follow the
-instructions found at:
-
- http://wiki.g2.bx.psu.edu/Admin/Config/Performance/Cluster
-
-Additional errors may follow:
-%s
-"""
-
-
-try:
- pkg_resources.require( "DRMAA_python" )
- import DRMAA
-except Exception, e:
- raise Exception( egg_message % str( e ) )
-
-
-log = logging.getLogger( __name__ )
-
-__all__ = [ 'SGEJobRunner' ]
-
-DRMAA_state = {
- DRMAA.Session.UNDETERMINED: 'process status cannot be determined',
- DRMAA.Session.QUEUED_ACTIVE: 'job is queued and waiting to be scheduled',
- DRMAA.Session.SYSTEM_ON_HOLD: 'job is queued and in system hold',
- DRMAA.Session.USER_ON_HOLD: 'job is queued and in user hold',
- DRMAA.Session.USER_SYSTEM_ON_HOLD: 'job is queued and in user and system hold',
- DRMAA.Session.RUNNING: 'job is running',
- DRMAA.Session.SYSTEM_SUSPENDED: 'job is system suspended',
- DRMAA.Session.USER_SUSPENDED: 'job is user suspended',
- DRMAA.Session.DONE: 'job finished normally',
- DRMAA.Session.FAILED: 'job finished, but failed',
-}
-
-sge_template = """#!/bin/sh
-#$ -S /bin/sh
-GALAXY_LIB="%s"
-if [ "$GALAXY_LIB" != "None" ]; then
- if [ -n "$PYTHONPATH" ]; then
- PYTHONPATH="$GALAXY_LIB:$PYTHONPATH"
- else
- PYTHONPATH="$GALAXY_LIB"
- fi
- export PYTHONPATH
-fi
-cd %s
-%s
-"""
-
-class SGEJobState( object ):
- def __init__( self ):
- """
- Encapsulates state related to a job that is being run via SGE and
- that we need to monitor.
- """
- self.job_wrapper = None
- self.job_id = None
- self.old_state = None
- self.running = False
- self.job_file = None
- self.ofile = None
- self.efile = None
- self.runner_url = None
-
-class SGEJobRunner( BaseJobRunner ):
- """
- Job runner backed by a finite pool of worker threads. FIFO scheduling
- """
- STOP_SIGNAL = object()
- def __init__( self, app ):
- """Initialize this job runner and start the monitor thread"""
- self.app = app
- self.sa_session = app.model.context
- # 'watched' and 'queue' are both used to keep track of jobs to watch.
- # 'queue' is used to add new watched jobs, and can be called from
- # any thread (usually by the 'queue_job' method). 'watched' must only
- # be modified by the monitor thread, which will move items from 'queue'
- # to 'watched' and then manage the watched jobs.
- self.watched = []
- self.monitor_queue = Queue()
- self.default_cell = self.determine_sge_cell( self.app.config.default_cluster_job_runner )
- self.ds = DRMAA.Session()
- self.ds.init( self.default_cell )
- self.monitor_thread = threading.Thread( target=self.monitor )
- self.monitor_thread.start()
- self.work_queue = Queue()
- self.work_threads = []
- nworkers = app.config.cluster_job_queue_workers
- for i in range( nworkers ):
- worker = threading.Thread( target=self.run_next )
- worker.start()
- self.work_threads.append( worker )
- log.debug( "%d workers ready" % nworkers )
-
- def determine_sge_cell( self, url ):
- """Determine what SGE cell we are using"""
- url_split = url.split("/")
- if url_split[0] == 'sge:':
- return url_split[2]
- # this could happen if sge is started, but is not the default runner
- else:
- return ''
-
- def determine_sge_queue( self, url ):
- """Determine what SGE queue we are submitting to"""
- try:
- return url.split('/')[3] or None
- except:
- return None
-
- def determine_sge_project( self, url ):
- """Determine what SGE project we are submitting to"""
- try:
- return url.split('/')[4] or None
- except:
- return None
-
- def determine_sge_tool_parameters( self, url ):
- """Determine what are the tool's specific paramters"""
- try:
- return url.split('/')[5] or None
- except:
- return None
-
- def run_next( self ):
- """
- Run the next item in the queue (a job waiting to run or finish )
- """
- while 1:
- ( op, obj ) = self.work_queue.get()
- if op is self.STOP_SIGNAL:
- return
- try:
- if op == 'queue':
- self.queue_job( obj )
- elif op == 'finish':
- self.finish_job( obj )
- elif op == 'fail':
- self.fail_job( obj )
- except:
- log.exception( "Uncaught exception %sing job" % op )
-
- def queue_job( self, job_wrapper ):
- """Create SGE script for a job and submit it to the SGE queue"""
-
- try:
- job_wrapper.prepare()
- command_line = self.build_command_line( job_wrapper, include_metadata = True )
- except:
- job_wrapper.fail( "failure preparing job", exception=True )
- log.exception("failure running job %d" % job_wrapper.job_id)
- return
-
- runner_url = job_wrapper.get_job_runner_url()
-
- # This is silly, why would we queue a job with no command line?
- if not command_line:
- job_wrapper.finish( '', '' )
- return
-
- # Check for deletion before we change state
- if job_wrapper.get_state() == model.Job.states.DELETED:
- log.debug( "Job %s deleted by user before it entered the SGE queue" % job_wrapper.job_id )
- job_wrapper.cleanup()
- return
-
- # Change to queued state immediately
- job_wrapper.change_state( model.Job.states.QUEUED )
-
- if self.determine_sge_cell( runner_url ) != self.default_cell:
- # TODO: support multiple cells
- log.warning( "(%s) Using multiple SGE cells is not supported. This job will be submitted to the default cell." % job_wrapper.job_id )
- sge_queue_name = self.determine_sge_queue( runner_url )
- sge_project_name = self.determine_sge_project( runner_url )
- sge_extra_params = self.determine_sge_tool_parameters ( runner_url )
-
- # define job attributes
- ofile = "%s/%s.o" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
- efile = "%s/%s.e" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
- jt = self.ds.createJobTemplate()
- jt.remoteCommand = "%s/database/pbs/galaxy_%s.sh" % (os.getcwd(), job_wrapper.job_id)
- jt.outputPath = ":%s" % ofile
- jt.errorPath = ":%s" % efile
- nativeSpec = []
- if sge_queue_name is not None:
- nativeSpec.append( "-q '%s'" % sge_queue_name )
- if sge_project_name is not None:
- nativeSpec.append( "-P '%s'" % sge_project_name)
- if sge_extra_params is not None:
- nativeSpec.append( sge_extra_params )
- if len(nativeSpec)>0:
- jt.nativeSpecification = ' '.join(nativeSpec)
-
- script = sge_template % (job_wrapper.galaxy_lib_dir, os.path.abspath( job_wrapper.working_directory ), command_line)
-
- fh = file( jt.remoteCommand, "w" )
- fh.write( script )
- fh.close()
- os.chmod( jt.remoteCommand, 0750 )
-
- # job was deleted while we were preparing it
- if job_wrapper.get_state() == model.Job.states.DELETED:
- log.debug( "Job %s deleted by user before it entered the SGE queue" % job_wrapper.job_id )
- self.cleanup( ( ofile, efile, jt.remoteCommand ) )
- job_wrapper.cleanup()
- return
-
- galaxy_job_id = job_wrapper.job_id
- log.debug("(%s) submitting file %s" % ( galaxy_job_id, jt.remoteCommand ) )
- log.debug("(%s) command is: %s" % ( galaxy_job_id, command_line ) )
- # runJob will raise if there's a submit problem
- job_id = self.ds.runJob(jt)
- if sge_queue_name is None:
- log.debug("(%s) queued in default queue as %s" % (galaxy_job_id, job_id) )
- else:
- log.debug("(%s) queued in %s queue as %s" % (galaxy_job_id, sge_queue_name, job_id) )
-
- # store runner information for tracking if Galaxy restarts
- job_wrapper.set_runner( runner_url, job_id )
-
- # Store SGE related state information for job
- sge_job_state = SGEJobState()
- sge_job_state.job_wrapper = job_wrapper
- sge_job_state.job_id = job_id
- sge_job_state.ofile = ofile
- sge_job_state.efile = efile
- sge_job_state.job_file = jt.remoteCommand
- sge_job_state.old_state = 'new'
- sge_job_state.running = False
- sge_job_state.runner_url = runner_url
-
- # delete the job template
- self.ds.deleteJobTemplate( jt )
-
- # Add to our 'queue' of jobs to monitor
- self.monitor_queue.put( sge_job_state )
-
- def monitor( self ):
- """
- Watches jobs currently in the PBS queue and deals with state changes
- (queued to running) and job completion
- """
- while 1:
- # Take any new watched jobs and put them on the monitor list
- try:
- while 1:
- sge_job_state = self.monitor_queue.get_nowait()
- if sge_job_state is self.STOP_SIGNAL:
- # TODO: This is where any cleanup would occur
- self.ds.exit()
- return
- self.watched.append( sge_job_state )
- except Empty:
- pass
- # Iterate over the list of watched jobs and check state
- self.check_watched_items()
- # Sleep a bit before the next state check
- time.sleep( 1 )
-
- def check_watched_items( self ):
- """
- Called by the monitor thread to look at each watched job and deal
- with state changes.
- """
- new_watched = []
- for sge_job_state in self.watched:
- job_id = sge_job_state.job_id
- galaxy_job_id = sge_job_state.job_wrapper.job_id
- old_state = sge_job_state.old_state
- try:
- state = self.ds.getJobProgramStatus( job_id )
- except DRMAA.InvalidJobError:
- # we should only get here if an orphaned job was put into the queue at app startup
- log.debug("(%s/%s) job left SGE queue" % ( galaxy_job_id, job_id ) )
- self.work_queue.put( ( 'finish', sge_job_state ) )
- continue
- except Exception, e:
- # so we don't kill the monitor thread
- log.exception("(%s/%s) Unable to check job status" % ( galaxy_job_id, job_id ) )
- log.warning("(%s/%s) job will now be errored" % ( galaxy_job_id, job_id ) )
- sge_job_state.fail_message = "Cluster could not complete job"
- self.work_queue.put( ( 'fail', sge_job_state ) )
- continue
- if state != old_state:
- log.debug("(%s/%s) state change: %s" % ( galaxy_job_id, job_id, DRMAA_state[state] ) )
- if state == DRMAA.Session.RUNNING and not sge_job_state.running:
- sge_job_state.running = True
- sge_job_state.job_wrapper.change_state( model.Job.states.RUNNING )
- if state in ( DRMAA.Session.DONE, DRMAA.Session.FAILED ):
- self.work_queue.put( ( 'finish', sge_job_state ) )
- continue
- sge_job_state.old_state = state
- new_watched.append( sge_job_state )
- # Replace the watch list with the updated version
- self.watched = new_watched
-
- def finish_job( self, sge_job_state ):
- """
- Get the output/error for a finished job, pass to `job_wrapper.finish`
- and cleanup all the SGE temporary files.
- """
- ofile = sge_job_state.ofile
- efile = sge_job_state.efile
- job_file = sge_job_state.job_file
- # collect the output
- try:
- ofh = file(ofile, "r")
- efh = file(efile, "r")
- stdout = ofh.read( 32768 )
- stderr = efh.read( 32768 )
- except:
- stdout = ''
- stderr = 'Job output not returned from cluster'
- log.debug(stderr)
-
- try:
- sge_job_state.job_wrapper.finish( stdout, stderr )
- except:
- log.exception("Job wrapper finish method failed")
-
- # clean up the sge files
- self.cleanup( ( ofile, efile, job_file ) )
-
- def fail_job( self, sge_job_state ):
- """
- Seperated out so we can use the worker threads for it.
- """
- self.stop_job( self.sa_session.query( self.app.model.Job ).get( sge_job_state.job_wrapper.job_id ) )
- sge_job_state.job_wrapper.fail( sge_job_state.fail_message )
- self.cleanup( ( sge_job_state.ofile, sge_job_state.efile, sge_job_state.job_file ) )
-
- def cleanup( self, files ):
- if not asbool( self.app.config.get( 'debug', False ) ):
- for file in files:
- if os.access( file, os.R_OK ):
- os.unlink( file )
-
- def put( self, job_wrapper ):
- """Add a job to the queue (by job identifier)"""
- # Change to queued state before handing to worker thread so the runner won't pick it up again
- job_wrapper.change_state( model.Job.states.QUEUED )
- self.work_queue.put( ( 'queue', job_wrapper ) )
-
- def shutdown( self ):
- """Attempts to gracefully shut down the monitor thread"""
- log.info( "sending stop signal to worker threads" )
- self.monitor_queue.put( self.STOP_SIGNAL )
- for i in range( len( self.work_threads ) ):
- self.work_queue.put( ( self.STOP_SIGNAL, None ) )
- log.info( "sge job runner stopped" )
-
- def stop_job( self, job ):
- """Attempts to delete a job from the SGE queue"""
- try:
- self.ds.control( job.get_job_runner_external_id(), DRMAA.Session.TERMINATE )
- log.debug( "(%s/%s) Removed from SGE queue at user's request" % ( job.get_id(), job.get_job_runner_external_id() ) )
- except DRMAA.InvalidJobError:
- log.debug( "(%s/%s) User killed running job, but it was already dead" % ( job.get_id(), job.get_job_runner_external_id() ) )
-
- def recover( self, job, job_wrapper ):
- """Recovers jobs stuck in the queued/running state when Galaxy started"""
- sge_job_state = SGEJobState()
- sge_job_state.ofile = "%s/database/pbs/%s.o" % (os.getcwd(), job.get_id())
- sge_job_state.efile = "%s/database/pbs/%s.e" % (os.getcwd(), job.get_id())
- sge_job_state.job_file = "%s/database/pbs/galaxy_%s.sh" % (os.getcwd(), job.get_id())
- sge_job_state.job_id = str( job.get_job_runner_external_id() )
- sge_job_state.runner_url = job_wrapper.get_job_runner_url()
- job_wrapper.command_line = job.get_command_line()
- sge_job_state.job_wrapper = job_wrapper
- if job.get_state() == model.Job.states.RUNNING:
- log.debug( "(%s/%s) is still in running state, adding to the SGE queue" % ( job.get_id(), job.get_job_runner_external_id() ) )
- sge_job_state.old_state = DRMAA.Session.RUNNING
- sge_job_state.running = True
- self.monitor_queue.put( sge_job_state )
- elif job.get_state() == model.Job.states.QUEUED:
- log.debug( "(%s/%s) is still in SGE queued state, adding to the SGE queue" % ( job.get_id(), job.get_job_runner_external_id() ) )
- sge_job_state.old_state = DRMAA.Session.QUEUED_ACTIVE
- sge_job_state.running = False
- self.monitor_queue.put( sge_job_state )
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -4,24 +4,23 @@
Naming: try to use class names that have a distinct plural form so that
the relationship cardinalities are obvious (e.g. prefer Dataset to Data)
"""
+
import pkg_resources
-pkg_resources.require( "simplejson" )
-import simplejson
+pkg_resources.require("simplejson")
+pkg_resources.require("pexpect")
+import simplejson, os, errno, codecs, operator, socket, pexpect, logging, time
import galaxy.datatypes
-from galaxy.util.bunch import Bunch
-from galaxy import util
import galaxy.datatypes.registry
from galaxy.datatypes.metadata import MetadataCollection
-from galaxy.security import RBACAgent, get_permitted_actions
-from galaxy.util.hash_util import *
-from galaxy.web.form_builder import *
+from galaxy.security import get_permitted_actions
+from galaxy import util
+from galaxy.util.bunch import Bunch
+from galaxy.util.hash_util import new_secure_hash
+from galaxy.web.form_builder import (AddressField, CheckboxField, PasswordField, SelectField, TextArea, TextField,
+ WorkflowField, WorkflowMappingField, HistoryField)
from galaxy.model.item_attrs import UsesAnnotations, APIItem
from sqlalchemy.orm import object_session
from sqlalchemy.sql.expression import func
-import os.path, os, errno, codecs, operator, socket, pexpect, logging, time, shutil
-
-if sys.version_info[:2] < ( 2, 5 ):
- from sets import Set as set
log = logging.getLogger( __name__ )
@@ -138,13 +137,13 @@
self.exit_code = None
# TODO: Add accessors for members defined in SQL Alchemy for the Job table and
- # for the mapper defined to the Job table.
+ # for the mapper defined to the Job table.
def get_external_output_metadata( self ):
"""
- The external_output_metadata is currently a reference from Job to
+ The external_output_metadata is currently a reference from Job to
JobExternalOutputMetadata. It exists for a job but not a task.
"""
- return self.external_output_metadata
+ return self.external_output_metadata
def get_session_id( self ):
return self.session_id
def get_user_id( self ):
@@ -177,7 +176,7 @@
# runner_name is not the same thing.
return self.job_runner_name
def get_job_runner_external_id( self ):
- # This is different from the Task just in the member accessed:
+ # This is different from the Task just in the member accessed:
return self.job_runner_external_id
def get_post_job_actions( self ):
return self.post_job_actions
@@ -197,10 +196,10 @@
# The tasks member is pert of a reference in the SQL Alchemy schema:
return self.tasks
def get_id_tag( self ):
- """
- Return a tag that can be useful in identifying a Job.
+ """
+ Return a tag that can be useful in identifying a Job.
This returns the Job's get_id
- """
+ """
return "%s" % self.id;
def set_session_id( self, session_id ):
@@ -324,8 +323,8 @@
self.task_runner_name = None
self.task_runner_external_id = None
self.job = job
- self.stdout = ""
- self.stderr = ""
+ self.stdout = ""
+ self.stderr = ""
self.exit_code = None
self.prepare_input_files_cmd = prepare_files_cmd
@@ -340,8 +339,8 @@
return param_dict
def get_id( self ):
- # This is defined in the SQL Alchemy schema:
- return self.id
+ # This is defined in the SQL Alchemy schema:
+ return self.id
def get_id_tag( self ):
"""
Return an id tag suitable for identifying the task.
@@ -378,7 +377,7 @@
# metdata). These can be filled in as needed.
def get_external_output_metadata( self ):
"""
- The external_output_metadata is currently a backref to
+ The external_output_metadata is currently a backref to
JobExternalOutputMetadata. It exists for a job but not a task,
and when a task is cancelled its corresponding parent Job will
be cancelled. So None is returned now, but that could be changed
@@ -395,13 +394,13 @@
"""
Runners will use the same methods to get information about the Task
class as they will about the Job class, so this method just returns
- the task's external id.
+ the task's external id.
"""
# TODO: Merge into get_runner_external_id.
return self.task_runner_external_id
def get_session_id( self ):
# The Job's galaxy session is equal to the Job's session, so the
- # Job's session is the same as the Task's session.
+ # Job's session is the same as the Task's session.
return self.get_job().get_session_id()
def set_id( self, id ):
@@ -424,7 +423,7 @@
# This method is available for runners that do not want/need to
# differentiate between the kinds of Runnable things (Jobs and Tasks)
# that they're using.
- log.debug( "Task %d: Set external id to %s"
+ log.debug( "Task %d: Set external id to %s"
% ( self.id, task_runner_external_id ) )
self.task_runner_external_id = task_runner_external_id
def set_task_runner_external_id( self, task_runner_external_id ):
@@ -701,8 +700,8 @@
def resume_paused_jobs( self ):
for dataset in self.datasets:
job = dataset.creating_job
- if job.state == Job.states.PAUSED:
- job.set_state(Job.states.QUEUED)
+ if job is not None and job.state == Job.states.PAUSED:
+ job.set_state(Job.states.NEW)
def get_disk_size( self, nice_size=False ):
# unique datasets only
db_session = object_session( self )
@@ -870,6 +869,7 @@
EMPTY = 'empty',
ERROR = 'error',
DISCARDED = 'discarded',
+ PAUSED = 'paused',
SETTING_METADATA = 'setting_metadata',
FAILED_METADATA = 'failed_metadata' )
permitted_actions = get_permitted_actions( filter='DATASET' )
@@ -953,7 +953,7 @@
return False
try:
return util.is_multi_byte( codecs.open( self.file_name, 'r', 'utf-8' ).read( 100 ) )
- except UnicodeDecodeError, e:
+ except UnicodeDecodeError:
return False
# FIXME: sqlalchemy will replace this
def _delete(self):
@@ -1135,7 +1135,6 @@
"""
Returns dict of { "dependency" => HDA }
"""
- converted_dataset = self.get_converted_files_by_type( target_ext )
# List of string of dependencies
try:
depends_list = trans.app.datatypes_registry.converter_deps[self.extension][target_ext]
@@ -1306,7 +1305,7 @@
"""
Returns datasources for dataset; if datasources are not available
due to indexing, indexing is started. Return value is a dictionary
- with entries of type
+ with entries of type
(<datasource_type> : {<datasource_name>, <indexing_message>}).
"""
track_type, data_sources = self.datatype.get_track_type()
@@ -1319,17 +1318,17 @@
else:
# Convert.
msg = self.convert_dataset( trans, data_source )
-
+
# Store msg.
data_sources_dict[ source_type ] = { "name" : data_source, "message": msg }
-
+
return data_sources_dict
def convert_dataset( self, trans, target_type ):
"""
- Converts a dataset to the target_type and returns a message indicating
+ Converts a dataset to the target_type and returns a message indicating
status of the conversion. None is returned to indicate that dataset
- was converted successfully.
+ was converted successfully.
"""
# FIXME: copied from controller.py
@@ -1401,7 +1400,7 @@
hda.metadata = self.metadata
if copy_children:
for child in self.children:
- child_copy = child.copy( copy_children = copy_children, parent_id = hda.id )
+ child.copy( copy_children = copy_children, parent_id = hda.id )
if not self.datatype.copy_safe_peek:
# In some instances peek relies on dataset_id, i.e. gmaj.zip for viewing MAFs
hda.set_peek()
@@ -1453,11 +1452,11 @@
object_session( self ).add( library_dataset )
object_session( self ).flush()
for child in self.children:
- child_copy = child.to_library_dataset_dataset_association( trans,
- target_folder=target_folder,
- replace_dataset=replace_dataset,
- parent_id=ldda.id,
- user=ldda.user )
+ child.to_library_dataset_dataset_association( trans,
+ target_folder=target_folder,
+ replace_dataset=replace_dataset,
+ parent_id=ldda.id,
+ user=ldda.user )
if not self.datatype.copy_safe_peek:
# In some instances peek relies on dataset_id, i.e. gmaj.zip for viewing MAFs
ldda.set_peek()
@@ -1807,7 +1806,7 @@
if add_to_history and target_history:
target_history.add_dataset( hda )
for child in self.children:
- child_copy = child.to_history_dataset_association( target_history = target_history, parent_id = hda.id, add_to_history = False )
+ child.to_history_dataset_association( target_history = target_history, parent_id = hda.id, add_to_history = False )
if not self.datatype.copy_safe_peek:
hda.set_peek() #in some instances peek relies on dataset_id, i.e. gmaj.zip for viewing MAFs
object_session( self ).flush()
@@ -1832,7 +1831,7 @@
ldda.metadata = self.metadata
if copy_children:
for child in self.children:
- child_copy = child.copy( copy_children = copy_children, parent_id = ldda.id )
+ child.copy( copy_children = copy_children, parent_id = ldda.id )
if not self.datatype.copy_safe_peek:
# In some instances peek relies on dataset_id, i.e. gmaj.zip for viewing MAFs
ldda.set_peek()
@@ -2639,7 +2638,7 @@
events={ '.ssword:*': scp_configs['password']+'\r\n',
pexpect.TIMEOUT:print_ticks},
timeout=10 )
- except Exception, e:
+ except Exception:
return error_msg
# cleanup the output to get just the file size
return output.replace( filepath, '' )\
@@ -3279,7 +3278,6 @@
.first()
return None
def get_versions( self, app ):
- sa_session = app.model.context.current
tool_versions = []
# Prepend ancestors.
def __ancestors( app, tool_version ):
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py
+++ b/lib/galaxy/model/mapping.py
@@ -1571,13 +1571,13 @@
) )
assign_mapper( context, JobToInputDatasetAssociation, JobToInputDatasetAssociation.table,
- properties=dict( job=relation( Job ), dataset=relation( HistoryDatasetAssociation, lazy=False ) ) )
+ properties=dict( job=relation( Job ), dataset=relation( HistoryDatasetAssociation, lazy=False, backref="dependent_jobs" ) ) )
assign_mapper( context, JobToOutputDatasetAssociation, JobToOutputDatasetAssociation.table,
properties=dict( job=relation( Job ), dataset=relation( HistoryDatasetAssociation, lazy=False ) ) )
assign_mapper( context, JobToInputLibraryDatasetAssociation, JobToInputLibraryDatasetAssociation.table,
- properties=dict( job=relation( Job ), dataset=relation( LibraryDatasetDatasetAssociation, lazy=False ) ) )
+ properties=dict( job=relation( Job ), dataset=relation( LibraryDatasetDatasetAssociation, lazy=False, backref="dependent_jobs" ) ) )
assign_mapper( context, JobToOutputLibraryDatasetAssociation, JobToOutputLibraryDatasetAssociation.table,
properties=dict( job=relation( Job ), dataset=relation( LibraryDatasetDatasetAssociation, lazy=False ) ) )
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/tool_shed/__init__.py
--- a/lib/galaxy/tool_shed/__init__.py
+++ b/lib/galaxy/tool_shed/__init__.py
@@ -53,4 +53,4 @@
galaxy.util.shed_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=deactivate )
if installed_repository_dict[ 'display_path' ]:
galaxy.util.shed_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=deactivate )
-
\ No newline at end of file
+
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/tool_shed/install_manager.py
--- a/lib/galaxy/tool_shed/install_manager.py
+++ b/lib/galaxy/tool_shed/install_manager.py
@@ -6,6 +6,7 @@
from galaxy.tools import ToolSection
from galaxy.util.json import from_json_string, to_json_string
from galaxy.util.shed_util import *
+from galaxy.util.shed_util_common import *
from galaxy.util.odict import odict
from galaxy.tool_shed.common_util import *
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/tool_shed/migrate/common.py
--- a/lib/galaxy/tool_shed/migrate/common.py
+++ b/lib/galaxy/tool_shed/migrate/common.py
@@ -2,6 +2,7 @@
import galaxy.config
import galaxy.datatypes.registry
from galaxy import tools
+from galaxy.tools.data import *
import galaxy.model.mapping
import galaxy.tools.search
from galaxy.objectstore import build_object_store_from_config
@@ -42,8 +43,8 @@
# Load the data types in the Galaxy distribution, which are defined in self.config.datatypes_config.
self.datatypes_registry.load_datatypes( self.config.root, self.config.datatypes_config )
# Initialize tool data tables using the config defined by self.config.tool_data_table_config_path.
- self.tool_data_tables = galaxy.tools.data.ToolDataTableManager( tool_data_path=self.config.tool_data_path,
- config_filename=self.config.tool_data_table_config_path )
+ self.tool_data_tables = ToolDataTableManager( tool_data_path=self.config.tool_data_path,
+ config_filename=self.config.tool_data_table_config_path )
# Load additional entries defined by self.config.shed_tool_data_table_config into tool data tables.
self.tool_data_tables.load_from_config_file( config_filename=self.config.shed_tool_data_table_config,
tool_data_path=self.tool_data_tables.tool_data_path,
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/tool_shed/migrate/versions/0007_tools.py
--- /dev/null
+++ b/lib/galaxy/tool_shed/migrate/versions/0007_tools.py
@@ -0,0 +1,17 @@
+"""
+The following tools have been eliminated from the distribution:
+Map with Bowtie for Illumina, Map with Bowtie for SOLiD, Lastz,
+and Lastz paired reads. The tools are now available in the
+repositories named bowtie_wrappers, bowtie_color_wrappers, lastz,
+and lastz_paired_reads from the main Galaxy tool shed at
+http://toolshed.g2.bx.psu.edu, and will be installed into your
+local Galaxy instance at the location discussed above by running
+the following command.
+"""
+
+import sys
+
+def upgrade():
+ print __doc__
+def downgrade():
+ pass
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/tool_shed/tool_dependencies/fabric_util.py
--- a/lib/galaxy/tool_shed/tool_dependencies/fabric_util.py
+++ b/lib/galaxy/tool_shed/tool_dependencies/fabric_util.py
@@ -58,7 +58,10 @@
action_type, action_dict = actions[ 0 ]
if action_type == 'download_by_url':
url = action_dict[ 'url' ]
- downloaded_filename = os.path.split( url )[ -1 ]
+ if 'target_filename' in action_dict:
+ downloaded_filename = action_dict[ 'target_filename' ]
+ else:
+ downloaded_filename = os.path.split( url )[ -1 ]
downloaded_file_path = common_util.url_download( work_dir, downloaded_filename, url )
if common_util.istar( downloaded_file_path ):
# <action type="download_by_url">http://sourceforge.net/projects/samtools/files/samtools/0.1.18/samtools-0.1…</action>
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/tool_shed/tool_dependencies/install_util.py
--- a/lib/galaxy/tool_shed/tool_dependencies/install_util.py
+++ b/lib/galaxy/tool_shed/tool_dependencies/install_util.py
@@ -135,6 +135,8 @@
# <action type="download_by_url">http://sourceforge.net/projects/samtools/files/samtools/0.1.18/samtools-0.1…</action>
if action_elem.text:
action_dict[ 'url' ] = action_elem.text
+ if 'target_filename' in action_elem.attrib:
+ action_dict[ 'target_filename' ] = action_elem.attrib[ 'target_filename' ]
else:
continue
elif action_type == 'make_directory':
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/tool_shed/update_manager.py
--- a/lib/galaxy/tool_shed/update_manager.py
+++ b/lib/galaxy/tool_shed/update_manager.py
@@ -4,6 +4,7 @@
import threading, urllib2, logging
from galaxy.util import string_as_bool
from galaxy.util.shed_util import *
+from galaxy.util.shed_util_common import *
log = logging.getLogger( __name__ )
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -34,6 +34,7 @@
from galaxy.util.hash_util import *
from galaxy.util import listify
from galaxy.util.shed_util import *
+from galaxy.util.shed_util_common import *
from galaxy.web import url_for
from galaxy.visualization.genome.visual_analytics import TracksterConfig
diff -r 53d3d620a8783a7ac4de9360e3691853681ffac3 -r e67fb0786e41de3bb1229a3be267a9bad07320a6 lib/galaxy/tools/data/__init__.py
--- a/lib/galaxy/tools/data/__init__.py
+++ b/lib/galaxy/tools/data/__init__.py
@@ -118,6 +118,14 @@
class ToolDataTable( object ):
def __init__( self, config_element, tool_data_path ):
self.name = config_element.get( 'name' )
+ self.comment_char = config_element.get( 'comment_char' )
+ for file_elem in config_element.findall( 'file' ):
+ # There should only be one file_elem.
+ if 'path' in file_elem.attrib:
+ tool_data_file_path = file_elem.get( 'path' )
+ self.tool_data_file = os.path.split( tool_data_file_path )[1]
+ else:
+ self.tool_data_file = None
self.tool_data_path = tool_data_path
self.missing_index_file = None
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/galaxy/galaxy-central/commits/aa07ef33632c/
changeset: aa07ef33632c
user: jmchilton
date: 2013-01-16 23:22:55
summary: Merge with latest galaxy-central to resolve conflict introduced with 4bd4197.
affected #: 6 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/301d7447dd22/
changeset: 301d7447dd22
user: dannon
date: 2013-01-30 00:08:43
summary: Merged in galaxyp/galaxy-central-parallelism-refactorings (pull request #87)
Refactoring Task Splitting Toward Per-Job Definitions (in Addition to Current Per-Tool Definitions)
affected #: 6 files
Diff not available.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2cfd745996f2/
changeset: 2cfd745996f2
user: jgoecks
date: 2013-01-29 22:40:04
summary: Fixes for packing metadata in HDA api values.
affected #: 1 file
diff -r 0c42ee613365a48220925982a67ee37e82bf66ff -r 2cfd745996f221d3819e31ac3ca2eb06c900738b lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1529,8 +1529,9 @@
val = hda.metadata.get( name )
if isinstance( val, MetadataFile ):
val = val.file_name
- elif isinstance( val, list ):
- val = ', '.join( [str(v) for v in val] )
+ # If no value for metadata, look in datatype for metadata.
+ elif val == None and hasattr( hda.datatype, name ):
+ val = getattr( hda.datatype, name )
rval['metadata_' + name] = val
return rval
https://bitbucket.org/galaxy/galaxy-central/commits/01cbf01a2072/
changeset: 01cbf01a2072
user: jgoecks
date: 2013-01-29 22:41:04
summary: Add metadata support to JavaScript dataset objects.
affected #: 1 file
diff -r 2cfd745996f221d3819e31ac3ca2eb06c900738b -r 01cbf01a20724514cda66a7071f1ecf376434157 static/scripts/mvc/data.js
--- a/static/scripts/mvc/data.js
+++ b/static/scripts/mvc/data.js
@@ -1,6 +1,11 @@
define(["libs/backbone/backbone-relational"], function() {
/**
+ * Dataset metedata.
+ */
+var DatasetMetadata = Backbone.RelationalModel.extend({});
+
+/**
* A dataset. In Galaxy, datasets are associated with a history, so
* this object is also known as a HistoryDatasetAssociation.
*/
@@ -9,7 +14,33 @@
id: '',
type: '',
name: '',
- hda_ldda: 'hda'
+ hda_ldda: 'hda',
+ metadata: null
+ },
+
+ initialize: function() {
+ // -- Create and initialize metadata. --
+
+ var metadata = new DatasetMetadata();
+
+ // Move metadata from dataset attributes to metadata object.
+ _.each(_.keys(this.attributes), function(k) {
+ if (k.indexOf('metadata_') === 0) {
+ // Found metadata.
+ var new_key = k.split('metadata_')[1];
+ metadata.set(new_key, this.attributes[k]);
+ delete this.attributes[k];
+ }
+ }, this);
+
+ this.set('metadata', metadata);
+ },
+
+ /**
+ * Returns dataset metadata for a given attribute.
+ */
+ get_metadata: function(attribute) {
+ return this.attributes.metadata.get(attribute);
},
urlRoot: galaxy_paths.get('datasets_url')
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0c42ee613365/
changeset: 0c42ee613365
user: jgoecks
date: 2013-01-29 20:34:42
summary: Documentation fix.
affected #: 1 file
diff -r a14006775b085be19454aa6d47655a6ebb68c8a1 -r 0c42ee613365a48220925982a67ee37e82bf66ff lib/galaxy/model/migrate/versions/0110_add_dataset_uuid.py
--- a/lib/galaxy/model/migrate/versions/0110_add_dataset_uuid.py
+++ b/lib/galaxy/model/migrate/versions/0110_add_dataset_uuid.py
@@ -39,7 +39,7 @@
def downgrade():
metadata.reflect()
- # Drop the Job table's exit_code column.
+ # Drop the dataset table's uuid column.
try:
dataset_table = Table( "dataset", metadata, autoload=True )
dataset_uuid = dataset_table.c.uuid
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Add parameter to filtering tool to optionally skip header lines. Add test for new parameter usage as well.
by Bitbucket 29 Jan '13
by Bitbucket 29 Jan '13
29 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a14006775b08/
changeset: a14006775b08
user: jgoecks
date: 2013-01-29 16:37:16
summary: Add parameter to filtering tool to optionally skip header lines. Add test for new parameter usage as well.
affected #: 4 files
diff -r 22788c1262a2756a50e03d92f8ee14705d019b98 -r a14006775b085be19454aa6d47655a6ebb68c8a1 test-data/filter1_in5.tab
--- /dev/null
+++ b/test-data/filter1_in5.tab
@@ -0,0 +1,5 @@
+tracking_id class_code nearest_ref_id gene_id gene_short_name tss_id locus length coverage replicate 1_FPKM replicate 1_conf_lo replicate 1_conf_hi replicate 1_status replicate 2_FPKM replicate 2_conf_lo replicate 2_conf_hi replicate 2_status
+CUFF.1.1 - - CUFF.1 - - chr19:305598-306225 627 - 0 0 0 OK 206.177 0 694.583 OK
+CUFF.10.1 - - CUFF.10 - - chr19:618402-618611 209 - 0 0 0 OK 767.201 0 2801.16 OK
+CUFF.100.1 - - CUFF.100 - - chr19:1625589-1652356 888 - 0 0 0 OK 172.566 0 2879.98 OK
+CUFF.100.2 - - CUFF.100 - - chr19:1625589-1652356 581 - 0 0 0 OK 1147.8 0 5922.31 OK
diff -r 22788c1262a2756a50e03d92f8ee14705d019b98 -r a14006775b085be19454aa6d47655a6ebb68c8a1 test-data/filter1_test5.tab
--- /dev/null
+++ b/test-data/filter1_test5.tab
@@ -0,0 +1,4 @@
+tracking_id class_code nearest_ref_id gene_id gene_short_name tss_id locus length coverage replicate 1_FPKM replicate 1_conf_lo replicate 1_conf_hi replicate 1_status replicate 2_FPKM replicate 2_conf_lo replicate 2_conf_hi replicate 2_status
+CUFF.1.1 - - CUFF.1 - - chr19:305598-306225 627 - 0 0 0 OK 206.177 0 694.583 OK
+CUFF.100.1 - - CUFF.100 - - chr19:1625589-1652356 888 - 0 0 0 OK 172.566 0 2879.98 OK
+CUFF.100.2 - - CUFF.100 - - chr19:1625589-1652356 581 - 0 0 0 OK 1147.8 0 5922.31 OK
diff -r 22788c1262a2756a50e03d92f8ee14705d019b98 -r a14006775b085be19454aa6d47655a6ebb68c8a1 tools/stats/filtering.py
--- a/tools/stats/filtering.py
+++ b/tools/stats/filtering.py
@@ -36,6 +36,7 @@
in_column_types = sys.argv[5].split( ',' )
except:
stop_err( "Data does not appear to be tabular. This tool can only be used with tab-delimited data." )
+num_header_lines = int( sys.argv[6] )
# Unescape if input has been escaped
mapped_str = {
@@ -98,6 +99,12 @@
for i, line in enumerate( file( in_fname ) ):
total_lines += 1
line = line.rstrip( '\\r\\n' )
+
+ if i < num_header_lines:
+ lines_kept += 1
+ print >> out, line
+ continue
+
if not line or line.startswith( '#' ):
skipped_lines += 1
continue
diff -r 22788c1262a2756a50e03d92f8ee14705d019b98 -r a14006775b085be19454aa6d47655a6ebb68c8a1 tools/stats/filtering.xml
--- a/tools/stats/filtering.xml
+++ b/tools/stats/filtering.xml
@@ -1,13 +1,14 @@
<tool id="Filter1" name="Filter" version="1.1.0"><description>data on any column using simple expressions</description><command interpreter="python">
- filtering.py $input $out_file1 "$cond" ${input.metadata.columns} "${input.metadata.column_types}"
+ filtering.py $input $out_file1 "$cond" ${input.metadata.columns} "${input.metadata.column_types}" $header_lines
</command><inputs><param format="tabular" name="input" type="data" label="Filter" help="Dataset missing? See TIP below."/><param name="cond" size="40" type="text" value="c1=='chr22'" label="With following condition" help="Double equal signs, ==, must be used as shown above. To filter for an arbitrary string, use the Select tool."><validator type="empty_field" message="Enter a valid filtering condition, see syntax and examples below."/></param>
+ <param name="header_lines" type="integer" value="0" label="Number of header lines to skip"/></inputs><outputs><data format="input" name="out_file1" metadata_source="input"/>
@@ -16,24 +17,34 @@
<test><param name="input" value="1.bed"/><param name="cond" value="c1=='chr22'"/>
+ <param name="header_lines" value="0"/><output name="out_file1" file="filter1_test1.bed"/></test><test><param name="input" value="7.bed"/><param name="cond" value="c1=='chr1' and c3-c2>=2000 and c6=='+'"/>
+ <param name="header_lines" value="0"/><output name="out_file1" file="filter1_test2.bed"/></test><!-- Test filtering of file with a variable number of columns. --><test><param name="input" value="filter1_in3.sam"/><param name="cond" value="c3=='chr1' and c5>5"/>
+ <param name="header_lines" value="0"/><output name="out_file1" file="filter1_test3.sam"/></test><test><param name="input" value="filter1_inbad.bed"/><param name="cond" value="c1=='chr22'"/>
+ <param name="header_lines" value="0"/><output name="out_file1" file="filter1_test4.bed"/></test>
+ <test>
+ <param name="input" value="filter1_in5.tab"/>
+ <param name="cond" value="c8>500"/>
+ <param name="header_lines" value="1"/>
+ <output name="out_file1" file="filter1_test5.tab"/>
+ </test></tests><help>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
28 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/22788c1262a2/
changeset: 22788c1262a2
user: jgoecks
date: 2013-01-28 22:36:02
summary: Language improvements for tophat wrappers.
affected #: 2 files
diff -r dfcc7e9469f81116ae01eb3aebf57b2a3d22ca82 -r 22788c1262a2756a50e03d92f8ee14705d019b98 tools/ngs_rna/tophat2_wrapper.xml
--- a/tools/ngs_rna/tophat2_wrapper.xml
+++ b/tools/ngs_rna/tophat2_wrapper.xml
@@ -144,15 +144,15 @@
</when></conditional><conditional name="refGenomeSource">
- <param name="genomeSource" type="select" label="Will you select a reference genome from your history or use a built-in index?" help="Built-ins were indexed using default options">
- <option value="indexed">Use a built-in index</option>
- <option value="history">Use one from the history</option>
+ <param name="genomeSource" type="select" label="Use a built in reference genome or own from your history" help="Built-in genomes were created using default options">
+ <option value="indexed" selected="True">Use a built-in genome</option>
+ <option value="history">Use a genome from history</option></param><when value="indexed"><param name="index" type="select" label="Select a reference genome" help="If your genome of interest is not listed, contact the Galaxy team"><options from_data_table="tophat2_indexes"><filter type="sort_by" column="2"/>
- <validator type="no_options" message="No indexes are available for the selected input dataset"/>
+ <validator type="no_options" message="No genomes are available for the selected input dataset"/></options></param></when>
diff -r dfcc7e9469f81116ae01eb3aebf57b2a3d22ca82 -r 22788c1262a2756a50e03d92f8ee14705d019b98 tools/ngs_rna/tophat_wrapper.xml
--- a/tools/ngs_rna/tophat_wrapper.xml
+++ b/tools/ngs_rna/tophat_wrapper.xml
@@ -152,15 +152,15 @@
<inputs><param format="fastqsanger" name="input1" type="data" label="RNA-Seq FASTQ file" help="Nucleotide-space: Must have Sanger-scaled quality values with ASCII offset 33" /><conditional name="refGenomeSource">
- <param name="genomeSource" type="select" label="Will you select a reference genome from your history or use a built-in index?" help="Built-ins were indexed using default options">
- <option value="indexed">Use a built-in index</option>
- <option value="history">Use one from the history</option>
+ <param name="genomeSource" type="select" label="Use a built in reference genome or own from your history" help="Built-ins genomes were created using default options">
+ <option value="indexed" selected="True">Use a built-in genome</option>
+ <option value="history">Use a genome from history</option></param><when value="indexed"><param name="index" type="select" label="Select a reference genome" help="If your genome of interest is not listed, contact the Galaxy team"><options from_data_table="tophat_indexes"><filter type="sort_by" column="2"/>
- <validator type="no_options" message="No indexes are available for the selected input dataset"/>
+ <validator type="no_options" message="No genomes are available for the selected input dataset"/></options></param></when>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/84d6dc6656ec/
changeset: 84d6dc6656ec
user: carlfeberhard
date: 2013-01-28 22:20:49
summary: History grid, view: allow user to view their own histories
affected #: 1 file
diff -r 149f0fc73fae0494fa5cf29ec719bf38981c01b6 -r 84d6dc6656ec2bcabfa6e298400f053af2ff7c35 lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -847,7 +847,9 @@
if not history_to_view:
return trans.show_error_message( "The specified history does not exist." )
# Admin users can view any history
- if not trans.user_is_admin() and not history_to_view.importable:
+ if( ( history_to_view.user != trans.user )
+ and ( not trans.user_is_admin() )
+ and ( not history_to_view.importable ) ):
error( "Either you are not allowed to view this history or the owner of this history has not made it accessible." )
# View history.
show_deleted = util.string_as_bool( show_deleted )
https://bitbucket.org/galaxy/galaxy-central/commits/dfcc7e9469f8/
changeset: dfcc7e9469f8
user: carlfeberhard
date: 2013-01-28 22:22:47
summary: history panel: log responseText of history-model update errors; pack scripts
affected #: 2 files
diff -r 84d6dc6656ec2bcabfa6e298400f053af2ff7c35 -r dfcc7e9469f81116ae01eb3aebf57b2a3d22ca82 static/scripts/mvc/history/history-model.js
--- a/static/scripts/mvc/history/history-model.js
+++ b/static/scripts/mvc/history/history-model.js
@@ -56,7 +56,7 @@
// if we've got hdas passed in the constructor, load them and set up updates if needed
if( initialHdas ){
- if( _.isArray( initialHdas ) ){
+ if( _.isArray( initialHdas ) ){
this.hdas.reset( initialHdas );
this.checkForUpdates();
@@ -192,6 +192,7 @@
//TODO: remove when iframes are removed
if( !( ( xhr.readyState === 0 ) && ( xhr.status === 0 ) ) ){
alert( _l( 'Error getting history updates from the server.' ) + '\n' + error );
+ history.log( 'stateUpdater error:', error, 'responseText:', xhr.responseText );
}
});
},
diff -r 84d6dc6656ec2bcabfa6e298400f053af2ff7c35 -r dfcc7e9469f81116ae01eb3aebf57b2a3d22ca82 static/scripts/packed/mvc/history/history-model.js
--- a/static/scripts/packed/mvc/history/history-model.js
+++ b/static/scripts/packed/mvc/history/history-model.js
@@ -1,1 +1,1 @@
-var History=BaseModel.extend(LoggableMixin).extend({defaults:{id:"",name:"",state:"",diskSize:0,deleted:false,annotation:null,message:null},urlRoot:"api/histories/",url:function(){return"api/histories/"+this.get("id")},initialize:function(a,b){this.log(this+".initialize:",a,b);this.hdas=new HDACollection();if(b){if(_.isArray(b)){this.hdas.reset(b);this.checkForUpdates()}else{if(_.isString(b)&&(b.match(/error/i))){alert(_l("Error loading bootstrapped history")+":\n"+b)}}}},loadFromApi:function(a,c){var b=this;b.attributes.id=a;jQuery.when(jQuery.ajax("api/users/current"),b.fetch()).then(function(e,d){b.attributes.user=e[0];b.trigger("loaded:user",e[0]);b.trigger("loaded",d[0])}).then(function(){jQuery.ajax(b.url()+"/contents?"+jQuery.param({ids:b.hdaIdsFromStateIds().join(",")})).success(function(d){b.hdas.reset(d);b.checkForUpdates();b.trigger("loaded:hdas",d);if(c){callback(b)}})})},hdaIdsFromStateIds:function(){return _.reduce(_.values(this.get("state_ids")),function(b,a){return b.concat(a)})},checkForUpdates:function(a){if(this.hdas.running().length){this.stateUpdater()}else{this.trigger("ready")}return this},stateUpdater:function(){var c=this,a=this.get("state"),b=this.get("state_ids");jQuery.ajax("api/histories/"+this.get("id")).success(function(d){c.set(d);c.log("current history state:",c.get("state"),"(was)",a,"new size:",c.get("nice_size"));var e=[];_.each(_.keys(d.state_ids),function(g){var f=_.difference(d.state_ids[g],b[g]);e=e.concat(f)});if(e.length){c.fetchHdaUpdates(e)}if((c.get("state")===HistoryDatasetAssociation.STATES.RUNNING)||(c.get("state")===HistoryDatasetAssociation.STATES.QUEUED)){setTimeout(function(){c.stateUpdater()},History.UPDATE_DELAY)}else{c.trigger("ready")}}).error(function(f,d,e){if(!((f.readyState===0)&&(f.status===0))){alert(_l("Error getting history updates from the server.")+"\n"+e)}})},fetchHdaUpdates:function(b){var a=this;jQuery.ajax({url:this.url()+"/contents?"+jQuery.param({ids:b.join(",")}),error:function(h,c,d){if((h.readyState===0)&&(h.status===0)){return}var f=JSON.parse(h.responseText);if(_.isArray(f)){var e=_.groupBy(f,function(i){if(_.has(i,"error")){return"errored"}return"ok"});a.log("fetched, errored datasets:",e.errored);a.updateHdas(f)}else{var g=_l("ERROR updating hdas from api history contents")+": ";a.log(g,b,h,c,d,errorJSON);alert(g+b.join(","))}},success:function(d,c,e){a.log(a+".fetchHdaUpdates, success:",c,e);a.updateHdas(d)}})},updateHdas:function(a){var c=this,b=[];c.log(c+".updateHdas:",a);_.each(a,function(e,f){var d=c.hdas.get(e.id);if(d){c.log("found existing model in list for id "+e.id+", updating...:");d.set(e)}else{c.log("NO existing model for id "+e.id+", creating...:");b.push(e)}});if(b.length){c.addHdas(b)}},addHdas:function(a){var b=this;_.each(a,function(c,d){var e=b.hdas.hidToCollectionIndex(c.hid);c.history_id=b.get("id");b.hdas.add(new HistoryDatasetAssociation(c),{at:e,silent:true})});b.hdas.trigger("add",a)},toString:function(){var a=(this.get("name"))?(","+this.get("name")):("");return"History("+this.get("id")+a+")"}});History.UPDATE_DELAY=4000;var HistoryCollection=Backbone.Collection.extend(LoggableMixin).extend({model:History,urlRoot:"api/histories"});
\ No newline at end of file
+var History=BaseModel.extend(LoggableMixin).extend({defaults:{id:"",name:"",state:"",diskSize:0,deleted:false,annotation:null,message:null},urlRoot:"api/histories/",url:function(){return"api/histories/"+this.get("id")},initialize:function(a,b){this.log(this+".initialize:",a,b);this.hdas=new HDACollection();if(b){if(_.isArray(b)){this.hdas.reset(b);this.checkForUpdates()}else{if(_.isString(b)&&(b.match(/error/i))){alert(_l("Error loading bootstrapped history")+":\n"+b)}}}},loadFromApi:function(a,c){var b=this;b.attributes.id=a;jQuery.when(jQuery.ajax("api/users/current"),b.fetch()).then(function(e,d){b.attributes.user=e[0];b.trigger("loaded:user",e[0]);b.trigger("loaded",d[0])}).then(function(){jQuery.ajax(b.url()+"/contents?"+jQuery.param({ids:b.hdaIdsFromStateIds().join(",")})).success(function(d){b.hdas.reset(d);b.checkForUpdates();b.trigger("loaded:hdas",d);if(c){callback(b)}})})},hdaIdsFromStateIds:function(){return _.reduce(_.values(this.get("state_ids")),function(b,a){return b.concat(a)})},checkForUpdates:function(a){if(this.hdas.running().length){this.stateUpdater()}else{this.trigger("ready")}return this},stateUpdater:function(){var c=this,a=this.get("state"),b=this.get("state_ids");jQuery.ajax("api/histories/"+this.get("id")).success(function(d){c.set(d);c.log("current history state:",c.get("state"),"(was)",a,"new size:",c.get("nice_size"));var e=[];_.each(_.keys(d.state_ids),function(g){var f=_.difference(d.state_ids[g],b[g]);e=e.concat(f)});if(e.length){c.fetchHdaUpdates(e)}if((c.get("state")===HistoryDatasetAssociation.STATES.RUNNING)||(c.get("state")===HistoryDatasetAssociation.STATES.QUEUED)){setTimeout(function(){c.stateUpdater()},History.UPDATE_DELAY)}else{c.trigger("ready")}}).error(function(f,d,e){if(!((f.readyState===0)&&(f.status===0))){alert(_l("Error getting history updates from the server.")+"\n"+e);c.log("stateUpdater error:",e,"responseText:",f.responseText)}})},fetchHdaUpdates:function(b){var a=this;jQuery.ajax({url:this.url()+"/contents?"+jQuery.param({ids:b.join(",")}),error:function(h,c,d){if((h.readyState===0)&&(h.status===0)){return}var f=JSON.parse(h.responseText);if(_.isArray(f)){var e=_.groupBy(f,function(i){if(_.has(i,"error")){return"errored"}return"ok"});a.log("fetched, errored datasets:",e.errored);a.updateHdas(f)}else{var g=_l("ERROR updating hdas from api history contents")+": ";a.log(g,b,h,c,d,errorJSON);alert(g+b.join(","))}},success:function(d,c,e){a.log(a+".fetchHdaUpdates, success:",c,e);a.updateHdas(d)}})},updateHdas:function(a){var c=this,b=[];c.log(c+".updateHdas:",a);_.each(a,function(e,f){var d=c.hdas.get(e.id);if(d){c.log("found existing model in list for id "+e.id+", updating...:");d.set(e)}else{c.log("NO existing model for id "+e.id+", creating...:");b.push(e)}});if(b.length){c.addHdas(b)}},addHdas:function(a){var b=this;_.each(a,function(c,d){var e=b.hdas.hidToCollectionIndex(c.hid);c.history_id=b.get("id");b.hdas.add(new HistoryDatasetAssociation(c),{at:e,silent:true})});b.hdas.trigger("add",a)},toString:function(){var a=(this.get("name"))?(","+this.get("name")):("");return"History("+this.get("id")+a+")"}});History.UPDATE_DELAY=4000;var HistoryCollection=Backbone.Collection.extend(LoggableMixin).extend({model:History,urlRoot:"api/histories"});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
28 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/149f0fc73fae/
changeset: 149f0fc73fae
user: jgoecks
date: 2013-01-28 20:02:25
summary: Grid framework refactoring to increase speed and ease of debugging: (1) create and use Backbone object for grid; (2) move grid javascript to its own file; (3) remove webapp parameter; (4) augment search box style so that search button does not wrap. Pack scripts.
affected #: 9 files
diff -r d4d5588574ccb7faea8abfb0f0ca9fe9b48e701e -r 149f0fc73fae0494fa5cf29ec719bf38981c01b6 lib/galaxy/web/framework/helpers/grids.py
--- a/lib/galaxy/web/framework/helpers/grids.py
+++ b/lib/galaxy/web/framework/helpers/grids.py
@@ -16,7 +16,6 @@
"""
Specifies the content and format of a grid (data table).
"""
- webapp = None
title = ""
exposed = True
model_class = None
@@ -56,7 +55,6 @@
def __call__( self, trans, **kwargs ):
# Get basics.
# FIXME: pretty sure this is only here to pass along, can likely be eliminated
- webapp = trans.webapp.name
status = kwargs.get( 'status', None )
message = kwargs.get( 'message', None )
# Build a base filter and sort key that is the combination of the saved state and defaults.
@@ -229,7 +227,6 @@
params = cur_filter_dict.copy()
params['sort'] = sort_key
params['async'] = ( 'async' in kwargs )
- params['webapp'] = webapp
trans.log_action( trans.get_user(), unicode( "grid.view" ), context, params )
# Render grid.
def url( *args, **kwargs ):
@@ -273,7 +270,6 @@
status = status,
message = message,
use_panels=self.use_panels,
- webapp=webapp,
show_item_checkboxes = ( self.show_item_checkboxes or
kwargs.get( 'show_item_checkboxes', '' ) in [ 'True', 'true' ] ),
# Pass back kwargs so that grid template can set and use args without
diff -r d4d5588574ccb7faea8abfb0f0ca9fe9b48e701e -r 149f0fc73fae0494fa5cf29ec719bf38981c01b6 static/june_2007_style/base.less
--- a/static/june_2007_style/base.less
+++ b/static/june_2007_style/base.less
@@ -1085,6 +1085,7 @@
vertical-align: bottom;
display: inline-block;
padding: 0;
+ white-space: nowrap;
// border: 1px solid #aaa;
}
.gray-background {
diff -r d4d5588574ccb7faea8abfb0f0ca9fe9b48e701e -r 149f0fc73fae0494fa5cf29ec719bf38981c01b6 static/june_2007_style/blue/base.css
--- a/static/june_2007_style/blue/base.css
+++ b/static/june_2007_style/blue/base.css
@@ -976,7 +976,7 @@
#advanced-search table{border-collapse:separate;}
.delete-search-icon{background:url(../images/delete_tag_icon_gray.png) center no-repeat;display:inline-block;width:10px;cursor:pointer;height:18px;vertical-align:middle;margin-left:2px;}
.search-box-input{border:0;float:left;outline:medium none;font-style:italic;font-size:inherit;}
-.search-box{vertical-align:bottom;display:inline-block;padding:0;}
+.search-box{vertical-align:bottom;display:inline-block;padding:0;white-space:nowrap;}
.gray-background{background-color:#DDDDDD;}
.loading-elt-overlay{background-color:white;opacity:0.5;width:100%;height:100%;z-index:14000;position:fixed;display:none;}
div.odd_row{background:#dadfef;}
diff -r d4d5588574ccb7faea8abfb0f0ca9fe9b48e701e -r 149f0fc73fae0494fa5cf29ec719bf38981c01b6 static/scripts/galaxy.grids.js
--- /dev/null
+++ b/static/scripts/galaxy.grids.js
@@ -0,0 +1,549 @@
+// External dependencies (for module management eventually): jQuery, Backbone, underscore
+
+// This is necessary so that, when nested arrays are used in ajax/post/get methods, square brackets ('[]') are
+// not appended to the identifier of a nested array.
+jQuery.ajaxSettings.traditional = true;
+
+// Initialize grid objects on load.
+$(document).ready(function() {
+ init_grid_elements();
+ init_grid_controls();
+
+ // Initialize text filters to select text on click and use normal font when user is typing.
+ $('input[type=text]').each(function() {
+ $(this).click(function() { $(this).select(); } )
+ .keyup(function () { $(this).css("font-style", "normal"); });
+ });
+});
+
+/**
+ * A Galaxy grid.
+ */
+var Grid = Backbone.Model.extend({
+ defaults: {
+ url_base: '',
+ async: false,
+ async_ops: [],
+ categorical_filters: [],
+ filters: {},
+ sort_key: null,
+ show_item_checkboxes: false,
+ cur_page: 1,
+ num_pages: 1,
+ operation: undefined,
+ item_ids: undefined
+ },
+
+ /**
+ * Return true if operation can be done asynchronously.
+ */
+ can_async_op: function(op) {
+ return _.indexOf(this.attributes.async_ops, op) !== -1;
+ },
+
+ /**
+ * Add filtering criterion.
+ */
+ add_filter: function(key, value, append) {
+ // Update URL arg with new condition.
+ if (append) {
+ // Update or append value.
+ var cur_val = this.attributes.key,
+ new_val;
+ if (cur_val === null || cur_val === undefined) {
+ new_val = value;
+ }
+ else if (typeof(cur_val) == "string") {
+ if (cur_val == "All") {
+ new_val = value;
+ } else {
+ // Replace string with array.
+ var values = [];
+ values[0] = cur_val;
+ values[1] = value;
+ new_val = values;
+ }
+ }
+ else {
+ // Current value is an array.
+ new_val = cur_val;
+ new_val.push(value);
+ }
+ this.attributes.filters[key] = new_val;
+ }
+ else {
+ // Replace value.
+ this.attributes.filters[key] = value;
+ }
+ },
+
+ /**
+ * Remove filtering criterion.
+ */
+ remove_filter: function(key, condition) {
+ var cur_val = this.attributes.filters[key];
+ if (cur_val === null || cur_val === undefined) {
+ return false;
+ }
+
+ var removed = true;
+ if (typeof(cur_val) === "string") {
+ if (cur_val == "All") {
+ // Unexpected. Throw error?
+ removed = false;
+ }
+ else {
+ // Remove condition.
+ delete this.attributes.filters[key];
+ }
+ }
+ else {
+ // Filter contains an array of conditions.
+ var condition_index = _.indexOf(cur_val, condition);
+ if (condition_index !== -1) {
+ cur_val.splice(condition_index, 1);
+ }
+ else {
+ removed = false;
+ }
+ }
+
+ return removed;
+ },
+
+ /**
+ * Returns URL data for obtaining a new grid.
+ */
+ get_url_data: function() {
+ var url_data = {
+ async: this.attributes.async,
+ sort: this.attributes.sort_key,
+ page: this.attributes.cur_page,
+ show_item_checkboxes: this.attributes.show_item_checkboxes,
+ operation: this.attributes.operation,
+ id: this.attributes.item_ids
+ };
+
+ // Add filter arguments to data, placing "f-" in front of all arguments.
+ // FIXME: when underscore updated, use pairs function().
+ var self = this;
+ _.each(_.keys(self.attributes.filters), function(k) {
+ url_data['f-' + k] = self.attributes.filters[k];
+ });
+
+ return url_data;
+ }
+});
+
+//
+// Code to handle grid operations: filtering, sorting, paging, and operations.
+//
+
+// Init operation buttons.
+function init_operation_buttons() {
+ // Initialize operation buttons.
+ $('input[name=operation]:submit').each(function() {
+ $(this).click( function() {
+ var operation_name = $(this).val();
+ // For some reason, $('input[name=id]:checked').val() does not return all ids for checked boxes.
+ // The code below performs this function.
+ var item_ids = [];
+ $('input[name=id]:checked').each(function() {
+ item_ids.push( $(this).val() );
+ });
+ do_operation(operation_name, item_ids);
+ });
+ });
+}
+
+// Initialize grid controls
+function init_grid_controls() {
+ init_operation_buttons();
+
+ // Initialize submit image elements.
+ $('.submit-image').each( function() {
+ // On mousedown, add class to simulate click.
+ $(this).mousedown( function() {
+ $(this).addClass('gray-background');
+ });
+
+ // On mouseup, add class to simulate click.
+ $(this).mouseup( function() {
+ $(this).removeClass('gray-background');
+ });
+ });
+
+ // Initialize sort links.
+ $('.sort-link').each( function() {
+ $(this).click( function() {
+ set_sort_condition( $(this).attr('sort_key') );
+ return false;
+ });
+ });
+
+ // Initialize page links.
+ $('.page-link > a').each( function() {
+ $(this).click( function() {
+ set_page( $(this).attr('page_num') );
+ return false;
+ });
+ });
+
+ // Initialize categorical filters.
+ $('.categorical-filter > a').each( function() {
+ $(this).click( function() {
+ set_categorical_filter( $(this).attr('filter_key'), $(this).attr('filter_val') );
+ return false;
+ });
+ });
+
+ // Initialize text filters.
+ $('.text-filter-form').each( function() {
+ $(this).submit( function() {
+ var column_key = $(this).attr('column_key');
+ var text_input_obj = $('#input-' + column_key + '-filter');
+ var text_input = text_input_obj.val();
+ text_input_obj.val('');
+ add_filter_condition(column_key, text_input, true);
+ return false;
+ });
+ });
+
+ // Initialize autocomplete for text inputs in search UI.
+ var t = $("#input-tags-filter");
+ if (t.length) {
+ t.autocomplete(history_tag_autocomplete_url,
+ { selectFirst: false, autoFill: false, highlight: false, mustMatch: false });
+ }
+
+ var t2 = $("#input-name-filter");
+ if (t2.length) {
+ t2.autocomplete(history_name_autocomplete_url,
+ { selectFirst: false, autoFill: false, highlight: false, mustMatch: false });
+ }
+
+ // Initialize standard, advanced search toggles.
+ $('.advanced-search-toggle').each( function() {
+ $(this).click( function() {
+ $("#standard-search").slideToggle('fast');
+ $('#advanced-search').slideToggle('fast');
+ return false;
+ });
+ });
+}
+
+// Initialize grid elements.
+function init_grid_elements() {
+ // Initialize grid selection checkboxes.
+ $(".grid").each( function() {
+ var checkboxes = $(this).find("input.grid-row-select-checkbox");
+ var check_count = $(this).find("span.grid-selected-count");
+ var update_checked = function() {
+ check_count.text( $(checkboxes).filter(":checked").length );
+ };
+
+ $(checkboxes).each( function() {
+ $(this).change(update_checked);
+ });
+ update_checked();
+ });
+
+ // Initialize item labels.
+ $(".label").each( function() {
+ // If href has an operation in it, do operation when clicked. Otherwise do nothing.
+ var href = $(this).attr('href');
+ if ( href !== undefined && href.indexOf('operation=') != -1 ) {
+ $(this).click( function() {
+ do_operation_from_href( $(this).attr('href') );
+ return false;
+ });
+ }
+ });
+
+ // Initialize ratings.
+ $('.community_rating_star').rating({});
+
+ // Initialize item menu operations.
+ make_popup_menus();
+}
+
+// Go back to page one; this is useful when a filter is applied.
+function go_page_one() {
+ // Need to go back to page 1 if not showing all.
+ var cur_page = grid.get('cur_page');
+ if (cur_page !== null && cur_page !== undefined && cur_page !== 'all') {
+ grid.set('cur_page', 1);
+ }
+}
+
+// Add a condition to the grid filter; this adds the condition and refreshes the grid.
+function add_filter_condition(name, value, append) {
+ // Do nothing is value is empty.
+ if (value === "") {
+ return false;
+ }
+
+ // Add condition to grid.
+ grid.add_filter(name, value, append);
+
+ // Add button that displays filter and provides a button to delete it.
+ var t = $("<span>" + value + "<a href='javascript:void(0);'><span class='delete-search-icon' /></a></span>");
+ t.addClass('text-filter-val');
+ t.click(function() {
+ // Remove filter condition.
+ grid.remove_filter(name, value);
+
+ // Remove visible element.
+ $(this).remove();
+
+ go_page_one();
+ update_grid();
+ });
+
+ var container = $('#' + name + "-filtering-criteria");
+ container.append(t);
+
+ go_page_one();
+ update_grid();
+}
+
+// Add tag to grid filter.
+function add_tag_to_grid_filter(tag_name, tag_value) {
+ // Put tag name and value together.
+ var tag = tag_name + (tag_value !== undefined && tag_value !== "" ? ":" + tag_value : "");
+ $('#advanced-search').show('fast');
+ add_filter_condition("tags", tag, true);
+}
+
+// Set sort condition for grid.
+function set_sort_condition(col_key) {
+ // Set new sort condition. New sort is col_key if sorting new column; if reversing sort on
+ // currently sorted column, sort is reversed.
+ var cur_sort = grid.get('sort_key');
+ var new_sort = col_key;
+ if (cur_sort.indexOf(col_key) !== -1) {
+ // Reverse sort.
+ if (cur_sort.substring(0,1) !== '-') {
+ new_sort = '-' + col_key;
+ } else {
+ // Sort reversed by using just col_key.
+ }
+ }
+
+ // Remove sort arrows elements.
+ $('.sort-arrow').remove();
+
+ // Add sort arrow element to new sort column.
+ var sort_arrow = (new_sort.substring(0,1) == '-') ? "↑" : "↓";
+ var t = $("<span>" + sort_arrow + "</span>").addClass('sort-arrow');
+ var th = $("#" + col_key + '-header');
+ th.append(t);
+
+ // Update grid.
+ grid.set('sort_key', new_sort);
+ go_page_one();
+ update_grid();
+}
+
+// Set new value for categorical filter.
+function set_categorical_filter(name, new_value) {
+ // Update filter hyperlinks to reflect new filter value.
+ var category_filter = grid.get('categorical_filters')[name],
+ cur_value = grid.get('filters')[name];
+ $("." + name + "-filter").each( function() {
+ var text = $.trim( $(this).text() );
+ var filter = category_filter[text];
+ var filter_value = filter[name];
+ if (filter_value == new_value) {
+ // Remove filter link since grid will be using this filter. It is assumed that
+ // this element has a single child, a hyperlink/anchor with text.
+ $(this).empty();
+ $(this).addClass("current-filter");
+ $(this).append(text);
+ } else if (filter_value == cur_value) {
+ // Add hyperlink for this filter since grid will no longer be using this filter. It is assumed that
+ // this element has a single child, a hyperlink/anchor.
+ $(this).empty();
+ var t = $("<a href='#'>" + text + "</a>");
+ t.click(function() {
+ set_categorical_filter( name, filter_value );
+ });
+ $(this).removeClass("current-filter");
+ $(this).append(t);
+ }
+ });
+
+ // Update grid.
+ grid.add_filter(name, new_value);
+ go_page_one();
+ update_grid();
+}
+
+// Set page to view.
+function set_page(new_page) {
+ // Update page hyperlink to reflect new page.
+ $(".page-link").each( function() {
+ var id = $(this).attr('id'),
+ page_num = parseInt( id.split("-")[2], 10 ), // Id has form 'page-link-<page_num>
+ cur_page = grid.get('cur_page'),
+ text;
+ if (page_num === new_page) {
+ // Remove link to page since grid will be on this page. It is assumed that
+ // this element has a single child, a hyperlink/anchor with text.
+ text = $(this).children().text();
+ $(this).empty();
+ $(this).addClass("inactive-link");
+ $(this).text(text);
+ }
+ else if (page_num === cur_page) {
+ // Add hyperlink to this page since grid will no longer be on this page. It is assumed that
+ // this element has a single child, a hyperlink/anchor.
+ text = $(this).text();
+ $(this).empty();
+ $(this).removeClass("inactive-link");
+ var t = $("<a href='#'>" + text + "</a>");
+ t.click(function() {
+ set_page(page_num);
+ });
+ $(this).append(t);
+ }
+ });
+
+ var maintain_page_links = true;
+ if (new_page === "all") {
+ grid.set('cur_page', new_page);
+ maintain_page_links = false;
+ } else {
+ grid.set('cur_page', parseInt(new_page, 10));
+ }
+ update_grid(maintain_page_links);
+}
+
+// Perform a grid operation.
+function do_operation(operation, item_ids) {
+ operation = operation.toLowerCase();
+
+ // Update grid.
+ grid.set({
+ operation: operation,
+ item_ids: item_ids
+ });
+
+ // Do operation. If operation cannot be performed asynchronously, redirect to location.
+ if (grid.can_async_op(operation)) {
+ update_grid(true);
+ }
+ else {
+ go_to_URL();
+ }
+}
+
+// Perform a hyperlink click that initiates an operation. If there is no operation, ignore click.
+function do_operation_from_href(href) {
+ // Get operation, id in hyperlink's href.
+ var href_parts = href.split("?");
+ if (href_parts.length > 1) {
+ var href_parms_str = href_parts[1];
+ var href_parms = href_parms_str.split("&");
+ var operation = null;
+ var id = -1;
+ for (var index = 0; index < href_parms.length; index++) {
+ if (href_parms[index].indexOf('operation') != -1) {
+ // Found operation parm; get operation value.
+ operation = href_parms[index].split('=')[1];
+ } else if (href_parms[index].indexOf('id') != -1) {
+ // Found id parm; get id value.
+ id = href_parms[index].split('=')[1];
+ }
+ }
+ // Do operation.
+ do_operation(operation, id);
+ return false;
+ }
+}
+
+// Navigate window to the URL defined by url_args. This method can be used to short-circuit grid AJAXing.
+function go_to_URL() {
+ // Not async request.
+ grid.set('async', false);
+
+ // Go.
+ window.location = grid.get('url_base') + "?" + $.param(grid.get_url_data());
+}
+
+// Update grid.
+function update_grid(maintain_page_links) {
+ // If grid is not using async, then go to URL.
+ if (!grid.get('async')) {
+ go_to_URL();
+ }
+
+ // If there's an operation, do POST; otherwise, do GET.
+ var method = (grid.get('operation') ? "POST" : "GET" );
+ $('.loading-elt-overlay').show(); // Show overlay to indicate loading and prevent user actions.
+ $.ajax({
+ type: method,
+ url: grid.get('url_base'),
+ data: grid.get_url_data(),
+ error: function() { alert( "Grid refresh failed" ); },
+ success: function(response_text) {
+ // HACK: use a simple string to separate the elements in the
+ // response: (1) table body; (2) number of pages in table; and (3) message.
+ var parsed_response_text = response_text.split("*****");
+
+ // Update grid body and footer.
+ $('#grid-table-body').html(parsed_response_text[0]);
+ // FIXME: this does not work at all; what's needed is a function
+ // that updates page links when number of pages changes.
+ $('#grid-table-footer').html(parsed_response_text[1]);
+
+ // Trigger custom event to indicate grid body has changed.
+ $('#grid-table-body').trigger('update');
+
+ // Init grid.
+ init_grid_elements();
+ init_operation_buttons();
+ make_popup_menus();
+
+ // Hide loading overlay.
+ $('.loading-elt-overlay').hide();
+
+ // Show message if there is one.
+ var message = $.trim( parsed_response_text[2] );
+ if (message !== "") {
+ $('#grid-message').html( message ).show();
+ setTimeout( function() { $('#grid-message').hide(); }, 5000);
+ }
+ },
+ complete: function() {
+ // Clear grid of transient request attributes.
+ grid.set({
+ operation: undefined,
+ item_ids: undefined
+ });
+ }
+ });
+}
+
+function check_all_items() {
+ var chk_all = document.getElementById('check_all'),
+ checks = document.getElementsByTagName('input'),
+ total = 0,
+ i;
+ if ( chk_all.checked === true ) {
+ for ( i=0; i < checks.length; i++ ) {
+ if ( checks[i].name.indexOf( 'id' ) !== -1) {
+ checks[i].checked = true;
+ total++;
+ }
+ }
+ }
+ else {
+ for ( i=0; i < checks.length; i++ ) {
+ if ( checks[i].name.indexOf( 'id' ) !== -1) {
+ checks[i].checked = false;
+ }
+ }
+ }
+ init_grid_elements();
+}
\ No newline at end of file
diff -r d4d5588574ccb7faea8abfb0f0ca9fe9b48e701e -r 149f0fc73fae0494fa5cf29ec719bf38981c01b6 static/scripts/packed/galaxy.grids.js
--- /dev/null
+++ b/static/scripts/packed/galaxy.grids.js
@@ -0,0 +1,1 @@
+jQuery.ajaxSettings.traditional=true;$(document).ready(function(){init_grid_elements();init_grid_controls();$("input[type=text]").each(function(){$(this).click(function(){$(this).select()}).keyup(function(){$(this).css("font-style","normal")})})});var Grid=Backbone.Model.extend({defaults:{url_base:"",async:false,async_ops:[],categorical_filters:[],filters:{},sort_key:null,show_item_checkboxes:false,cur_page:1,num_pages:1,operation:undefined,item_ids:undefined},can_async_op:function(a){return _.indexOf(this.attributes.async_ops,a)!==-1},add_filter:function(e,f,b){if(b){var c=this.attributes.key,a;if(c===null||c===undefined){a=f}else{if(typeof(c)=="string"){if(c=="All"){a=f}else{var d=[];d[0]=c;d[1]=f;a=d}}else{a=c;a.push(f)}}this.attributes.filters[e]=a}else{this.attributes.filters[e]=f}},remove_filter:function(b,e){var a=this.attributes.filters[b];if(a===null||a===undefined){return false}var d=true;if(typeof(a)==="string"){if(a=="All"){d=false}else{delete this.attributes.filters[b]}}else{var c=_.indexOf(a,e);if(c!==-1){a.splice(c,1)}else{d=false}}return d},get_url_data:function(){var a={async:this.attributes.async,sort:this.attributes.sort_key,page:this.attributes.cur_page,show_item_checkboxes:this.attributes.show_item_checkboxes,operation:this.attributes.operation,id:this.attributes.item_ids};var b=this;_.each(_.keys(b.attributes.filters),function(c){a["f-"+c]=b.attributes.filters[c]});return a}});function init_operation_buttons(){$("input[name=operation]:submit").each(function(){$(this).click(function(){var b=$(this).val();var a=[];$("input[name=id]:checked").each(function(){a.push($(this).val())});do_operation(b,a)})})}function init_grid_controls(){init_operation_buttons();$(".submit-image").each(function(){$(this).mousedown(function(){$(this).addClass("gray-background")});$(this).mouseup(function(){$(this).removeClass("gray-background")})});$(".sort-link").each(function(){$(this).click(function(){set_sort_condition($(this).attr("sort_key"));return false})});$(".page-link > a").each(function(){$(this).click(function(){set_page($(this).attr("page_num"));return false})});$(".categorical-filter > a").each(function(){$(this).click(function(){set_categorical_filter($(this).attr("filter_key"),$(this).attr("filter_val"));return false})});$(".text-filter-form").each(function(){$(this).submit(function(){var d=$(this).attr("column_key");var c=$("#input-"+d+"-filter");var e=c.val();c.val("");add_filter_condition(d,e,true);return false})});var a=$("#input-tags-filter");if(a.length){a.autocomplete(history_tag_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}var b=$("#input-name-filter");if(b.length){b.autocomplete(history_name_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}$(".advanced-search-toggle").each(function(){$(this).click(function(){$("#standard-search").slideToggle("fast");$("#advanced-search").slideToggle("fast");return false})})}function init_grid_elements(){$(".grid").each(function(){var b=$(this).find("input.grid-row-select-checkbox");var a=$(this).find("span.grid-selected-count");var c=function(){a.text($(b).filter(":checked").length)};$(b).each(function(){$(this).change(c)});c()});$(".label").each(function(){var a=$(this).attr("href");if(a!==undefined&&a.indexOf("operation=")!=-1){$(this).click(function(){do_operation_from_href($(this).attr("href"));return false})}});$(".community_rating_star").rating({});make_popup_menus()}function go_page_one(){var a=grid.get("cur_page");if(a!==null&&a!==undefined&&a!=="all"){grid.set("cur_page",1)}}function add_filter_condition(c,e,a){if(e===""){return false}grid.add_filter(c,e,a);var d=$("<span>"+e+"<a href='javascript:void(0);'><span class='delete-search-icon' /></a></span>");d.addClass("text-filter-val");d.click(function(){grid.remove_filter(c,e);$(this).remove();go_page_one();update_grid()});var b=$("#"+c+"-filtering-criteria");b.append(d);go_page_one();update_grid()}function add_tag_to_grid_filter(c,b){var a=c+(b!==undefined&&b!==""?":"+b:"");$("#advanced-search").show("fast");add_filter_condition("tags",a,true)}function set_sort_condition(f){var e=grid.get("sort_key");var d=f;if(e.indexOf(f)!==-1){if(e.substring(0,1)!=="-"){d="-"+f}else{}}$(".sort-arrow").remove();var c=(d.substring(0,1)=="-")?"↑":"↓";var a=$("<span>"+c+"</span>").addClass("sort-arrow");var b=$("#"+f+"-header");b.append(a);grid.set("sort_key",d);go_page_one();update_grid()}function set_categorical_filter(b,d){var a=grid.get("categorical_filters")[b],c=grid.get("filters")[b];$("."+b+"-filter").each(function(){var h=$.trim($(this).text());var f=a[h];var g=f[b];if(g==d){$(this).empty();$(this).addClass("current-filter");$(this).append(h)}else{if(g==c){$(this).empty();var e=$("<a href='#'>"+h+"</a>");e.click(function(){set_categorical_filter(b,g)});$(this).removeClass("current-filter");$(this).append(e)}}});grid.add_filter(b,d);go_page_one();update_grid()}function set_page(a){$(".page-link").each(function(){var g=$(this).attr("id"),e=parseInt(g.split("-")[2],10),c=grid.get("cur_page"),f;if(e===a){f=$(this).children().text();$(this).empty();$(this).addClass("inactive-link");$(this).text(f)}else{if(e===c){f=$(this).text();$(this).empty();$(this).removeClass("inactive-link");var d=$("<a href='#'>"+f+"</a>");d.click(function(){set_page(e)});$(this).append(d)}}});var b=true;if(a==="all"){grid.set("cur_page",a);b=false}else{grid.set("cur_page",parseInt(a,10))}update_grid(b)}function do_operation(b,a){b=b.toLowerCase();grid.set({operation:b,item_ids:a});if(grid.can_async_op(b)){update_grid(true)}else{go_to_URL()}}function do_operation_from_href(c){var f=c.split("?");if(f.length>1){var a=f[1];var e=a.split("&");var b=null;var g=-1;for(var d=0;d<e.length;d++){if(e[d].indexOf("operation")!=-1){b=e[d].split("=")[1]}else{if(e[d].indexOf("id")!=-1){g=e[d].split("=")[1]}}}do_operation(b,g);return false}}function go_to_URL(){grid.set("async",false);window.location=grid.get("url_base")+"?"+$.param(grid.get_url_data())}function update_grid(a){if(!grid.get("async")){go_to_URL()}var b=(grid.get("operation")?"POST":"GET");$(".loading-elt-overlay").show();$.ajax({type:b,url:grid.get("url_base"),data:grid.get_url_data(),error:function(){alert("Grid refresh failed")},success:function(d){var c=d.split("*****");$("#grid-table-body").html(c[0]);$("#grid-table-footer").html(c[1]);$("#grid-table-body").trigger("update");init_grid_elements();init_operation_buttons();make_popup_menus();$(".loading-elt-overlay").hide();var e=$.trim(c[2]);if(e!==""){$("#grid-message").html(e).show();setTimeout(function(){$("#grid-message").hide()},5000)}},complete:function(){grid.set({operation:undefined,item_ids:undefined})}})}function check_all_items(){var a=document.getElementById("check_all"),b=document.getElementsByTagName("input"),d=0,c;if(a.checked===true){for(c=0;c<b.length;c++){if(b[c].name.indexOf("id")!==-1){b[c].checked=true;d++}}}else{for(c=0;c<b.length;c++){if(b[c].name.indexOf("id")!==-1){b[c].checked=false}}}init_grid_elements()};
\ No newline at end of file
diff -r d4d5588574ccb7faea8abfb0f0ca9fe9b48e701e -r 149f0fc73fae0494fa5cf29ec719bf38981c01b6 static/scripts/packed/mvc/dataset/hda-base.js
--- a/static/scripts/packed/mvc/dataset/hda-base.js
+++ b/static/scripts/packed/mvc/dataset/hda-base.js
@@ -1,1 +1,1 @@
-var HDABaseView=BaseView.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(a){if(a.logger){this.logger=this.model.logger=a.logger}this.log(this+".initialize:",a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];if(!a.urlTemplates){throw ("HDAView needs urlTemplates on initialize")}this.urlTemplates=a.urlTemplates;this.expanded=a.expanded||false;this.model.bind("change",this.render,this)},render:function(){var b=this,e=this.model.get("id"),c=this.model.get("state"),a=$("<div/>").attr("id","historyItem-"+e),d=(this.$el.children().size()===0);this.$el.attr("id","historyItemContainer-"+e);this.urls=this._renderUrls(this.urlTemplates,this.model.toJSON());a.addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+c);a.append(this._render_warnings());a.append(this._render_titleBar());this._setUpBehaviors(a);this.body=$(this._render_body());a.append(this.body);this.$el.fadeOut("fast",function(){b.$el.children().remove();b.$el.append(a).fadeIn("fast",function(){b.log(b+" rendered:",b.$el);var f="rendered";if(d){f+=":initial"}else{if(b.model.inReadyState()){f+=":ready"}}b.trigger(f)})});return this},_renderUrls:function(d,a){var b=this,c={};_.each(d,function(e,f){if(_.isObject(e)){c[f]=b._renderUrls(e,a)}else{if(f==="meta_download"){c[f]=b._renderMetaDownloadUrls(e,a)}else{try{c[f]=_.template(e,a)}catch(g){throw (b+"._renderUrls error: "+g+"\n rendering:"+e+"\n with "+JSON.stringify(a))}}}});return c},_renderMetaDownloadUrls:function(b,a){return _.map(a.meta_files,function(c){return{url:_.template(b,{id:a.id,file_type:c.file_type}),file_type:c.file_type}})},_setUpBehaviors:function(a){a=a||this.$el;make_popup_menus(a);a.find(".tooltip").tooltip({placement:"bottom"})},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());return a},_render_displayButton:function(){if((!this.model.inReadyState())||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.displayButton=null;return null}var a={icon_class:"display",target:"galaxy_main"};if(this.model.get("purged")){a.enabled=false;a.title=_l("Cannot display datasets removed from disk")}else{a.title=_l("Display data in browser");a.href=this.urls.display}this.displayButton=new IconButtonView({model:new IconButton(a)});return this.displayButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HDABaseView.templates.titleLink(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});return HDABaseView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var a=this,b=$("<div/>").attr("id","primary-actions-"+this.model.get("id"));_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var a=HDABaseView.templates.downloadLinks(_.extend(this.model.toJSON(),{urls:this.urls}));return $(a)},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_displayApps:function(){if(!this.model.hasData()){return null}var a=$("<div/>").addClass("display-apps");if(!_.isEmpty(this.model.get("display_types"))){a.append(HDABaseView.templates.displayApps({displayApps:this.model.get("display_types")}))}if(!_.isEmpty(this.model.get("display_apps"))){a.append(HDABaseView.templates.displayApps({displayApps:this.model.get("display_apps")}))}return a},_render_peek:function(){if(!this.model.get("peek")){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(this.model.get("peek")))},_render_body:function(){var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: none");if(this.expanded){this._render_body_html(a);a.show()}return a},_render_body_html:function(a){a.html("");switch(this.model.get("state")){case HistoryDatasetAssociation.STATES.NEW:break;case HistoryDatasetAssociation.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryDatasetAssociation.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryDatasetAssociation.STATES.PAUSED:this._render_body_paused(a);break;case HistoryDatasetAssociation.STATES.QUEUED:this._render_body_queued(a);break;case HistoryDatasetAssociation.STATES.RUNNING:this._render_body_running(a);break;case HistoryDatasetAssociation.STATES.ERROR:this._render_body_error(a);break;case HistoryDatasetAssociation.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryDatasetAssociation.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryDatasetAssociation.STATES.EMPTY:this._render_body_empty(a);break;case HistoryDatasetAssociation.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryDatasetAssociation.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'))}a.append('<div style="clear: both"></div>');this._setUpBehaviors(a)},_render_body_not_viewable:function(a){a.append($("<div>"+_l("You do not have permission to view dataset")+".</div>"))},_render_body_uploading:function(a){a.append($("<div>"+_l("Dataset is uploading")+"</div>"))},_render_body_queued:function(a){a.append($("<div>"+_l("Job is waiting to run")+".</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_paused:function(a){a.append($("<div>"+_l("Job is paused. Use the history menu to unpause")+".</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_running:function(a){a.append("<div>"+_l("Job is currently running")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append((_l("An error occurred running this job")+": <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton])))},_render_body_discarded:function(a){a.append("<div>"+_l("The job creating this dataset was cancelled before completion")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_setting_metadata:function(a){a.append($("<div>"+_l("Metadata is being auto-detected")+".</div>"))},_render_body_empty:function(a){a.append($("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_failed_metadata:function(a){a.append($(HDABaseView.templates.failedMetadata(this.model.toJSON())));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));a.append('<div class="clear"/>');a.append(this._render_displayApps());a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility"},toggleBodyVisibility:function(c,a){var b=this;this.expanded=(a===undefined)?(!this.body.is(":visible")):(a);if(this.expanded){b._render_body_html(b.body);this.body.slideDown("fast",function(){b.trigger("body-expanded",b.model.get("id"))})}else{this.body.slideUp("fast",function(){b.trigger("body-collapsed",b.model.get("id"))})}},remove:function(b){var a=this;this.$el.fadeOut("fast",function(){a.$el.remove();if(b){b()}})},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+a+")"}});HDABaseView.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-hda-warning-messages"],titleLink:Handlebars.templates["template-hda-titleLink"],hdaSummary:Handlebars.templates["template-hda-hdaSummary"],downloadLinks:Handlebars.templates["template-hda-downloadLinks"],failedMetadata:Handlebars.templates["template-hda-failedMetadata"],displayApps:Handlebars.templates["template-hda-displayApps"]};
\ No newline at end of file
+var HDABaseView=BaseView.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(a){if(a.logger){this.logger=this.model.logger=a.logger}this.log(this+".initialize:",a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];if(!a.urlTemplates){throw ("HDAView needs urlTemplates on initialize")}this.urlTemplates=a.urlTemplates;this.expanded=a.expanded||false;this.model.bind("change",this.render,this)},render:function(){var b=this,e=this.model.get("id"),c=this.model.get("state"),a=$("<div/>").attr("id","historyItem-"+e),d=(this.$el.children().size()===0);this.$el.attr("id","historyItemContainer-"+e);this.urls=this._renderUrls(this.urlTemplates,this.model.toJSON());a.addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+c);a.append(this._render_warnings());a.append(this._render_titleBar());this._setUpBehaviors(a);this.body=$(this._render_body());a.append(this.body);this.$el.fadeOut("fast",function(){b.$el.children().remove();b.$el.append(a).fadeIn("fast",function(){b.log(b+" rendered:",b.$el);var f="rendered";if(d){f+=":initial"}else{if(b.model.inReadyState()){f+=":ready"}}b.trigger(f)})});return this},_renderUrls:function(d,a){var b=this,c={};_.each(d,function(e,f){if(_.isObject(e)){c[f]=b._renderUrls(e,a)}else{if(f==="meta_download"){c[f]=b._renderMetaDownloadUrls(e,a)}else{try{c[f]=_.template(e,a)}catch(g){throw (b+"._renderUrls error: "+g+"\n rendering:"+e+"\n with "+JSON.stringify(a))}}}});return c},_renderMetaDownloadUrls:function(b,a){return _.map(a.meta_files,function(c){return{url:_.template(b,{id:a.id,file_type:c.file_type}),file_type:c.file_type}})},_setUpBehaviors:function(a){a=a||this.$el;make_popup_menus(a);a.find(".tooltip").tooltip({placement:"bottom"})},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());return a},_render_displayButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.displayButton=null;return null}var a={icon_class:"display",target:"galaxy_main"};if(this.model.get("purged")){a.enabled=false;a.title=_l("Cannot display datasets removed from disk")}else{a.title=_l("Display data in browser");a.href=this.urls.display}this.displayButton=new IconButtonView({model:new IconButton(a)});return this.displayButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HDABaseView.templates.titleLink(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});return HDABaseView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var a=this,b=$("<div/>").attr("id","primary-actions-"+this.model.get("id"));_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var a=HDABaseView.templates.downloadLinks(_.extend(this.model.toJSON(),{urls:this.urls}));return $(a)},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_displayApps:function(){if(!this.model.hasData()){return null}var a=$("<div/>").addClass("display-apps");if(!_.isEmpty(this.model.get("display_types"))){a.append(HDABaseView.templates.displayApps({displayApps:this.model.get("display_types")}))}if(!_.isEmpty(this.model.get("display_apps"))){a.append(HDABaseView.templates.displayApps({displayApps:this.model.get("display_apps")}))}return a},_render_peek:function(){if(!this.model.get("peek")){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(this.model.get("peek")))},_render_body:function(){var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: none");if(this.expanded){this._render_body_html(a);a.show()}return a},_render_body_html:function(a){a.html("");switch(this.model.get("state")){case HistoryDatasetAssociation.STATES.NEW:break;case HistoryDatasetAssociation.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryDatasetAssociation.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryDatasetAssociation.STATES.PAUSED:this._render_body_paused(a);break;case HistoryDatasetAssociation.STATES.QUEUED:this._render_body_queued(a);break;case HistoryDatasetAssociation.STATES.RUNNING:this._render_body_running(a);break;case HistoryDatasetAssociation.STATES.ERROR:this._render_body_error(a);break;case HistoryDatasetAssociation.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryDatasetAssociation.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryDatasetAssociation.STATES.EMPTY:this._render_body_empty(a);break;case HistoryDatasetAssociation.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryDatasetAssociation.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'))}a.append('<div style="clear: both"></div>');this._setUpBehaviors(a)},_render_body_not_viewable:function(a){a.append($("<div>"+_l("You do not have permission to view dataset")+".</div>"))},_render_body_uploading:function(a){a.append($("<div>"+_l("Dataset is uploading")+"</div>"))},_render_body_queued:function(a){a.append($("<div>"+_l("Job is waiting to run")+".</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_paused:function(a){a.append($("<div>"+_l("Job is paused. Use the history menu to resume")+".</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_running:function(a){a.append("<div>"+_l("Job is currently running")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append((_l("An error occurred with this dataset")+": <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton])))},_render_body_discarded:function(a){a.append("<div>"+_l("The job creating this dataset was cancelled before completion")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_setting_metadata:function(a){a.append($("<div>"+_l("Metadata is being auto-detected")+".</div>"))},_render_body_empty:function(a){a.append($("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_failed_metadata:function(a){a.append($(HDABaseView.templates.failedMetadata(_.extend(this.model.toJSON(),{urls:this.urls}))));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));a.append('<div class="clear"/>');a.append(this._render_displayApps());a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility"},toggleBodyVisibility:function(c,a){var b=this;this.expanded=(a===undefined)?(!this.body.is(":visible")):(a);if(this.expanded){b._render_body_html(b.body);this.body.slideDown("fast",function(){b.trigger("body-expanded",b.model.get("id"))})}else{this.body.slideUp("fast",function(){b.trigger("body-collapsed",b.model.get("id"))})}},remove:function(b){var a=this;this.$el.fadeOut("fast",function(){a.$el.remove();if(b){b()}})},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+a+")"}});HDABaseView.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-hda-warning-messages"],titleLink:Handlebars.templates["template-hda-titleLink"],hdaSummary:Handlebars.templates["template-hda-hdaSummary"],downloadLinks:Handlebars.templates["template-hda-downloadLinks"],failedMetadata:Handlebars.templates["template-hda-failedMetadata"],displayApps:Handlebars.templates["template-hda-displayApps"]};
\ No newline at end of file
diff -r d4d5588574ccb7faea8abfb0f0ca9fe9b48e701e -r 149f0fc73fae0494fa5cf29ec719bf38981c01b6 static/scripts/packed/mvc/history/history-model.js
--- a/static/scripts/packed/mvc/history/history-model.js
+++ b/static/scripts/packed/mvc/history/history-model.js
@@ -1,1 +1,1 @@
-var History=BaseModel.extend(LoggableMixin).extend({defaults:{id:"",name:"",state:"",diskSize:0,deleted:false,annotation:null,message:null},urlRoot:"api/histories/",url:function(){return"api/histories/"+this.get("id")},initialize:function(a,b){this.log(this+".initialize:",a,b);this.hdas=new HDACollection();if(b&&b.length){this.hdas.reset(b);this.checkForUpdates()}},loadFromApi:function(a,c){var b=this;b.attributes.id=a;jQuery.when(jQuery.ajax("api/users/current"),b.fetch()).then(function(e,d){b.attributes.user=e[0];b.trigger("loaded:user",e[0]);b.trigger("loaded",d[0])}).then(function(){jQuery.ajax(b.url()+"/contents?"+jQuery.param({ids:b.hdaIdsFromStateIds().join(",")})).success(function(d){b.hdas.reset(d);b.checkForUpdates();b.trigger("loaded:hdas",d);if(c){callback(b)}})})},hdaIdsFromStateIds:function(){return _.reduce(_.values(this.get("state_ids")),function(b,a){return b.concat(a)})},checkForUpdates:function(a){if(this.hdas.running().length){this.stateUpdater()}else{this.trigger("ready")}return this},stateUpdater:function(){var c=this,a=this.get("state"),b=this.get("state_ids");jQuery.ajax("api/histories/"+this.get("id")).success(function(d){c.set(d);c.log("current history state:",c.get("state"),"(was)",a,"new size:",c.get("nice_size"));var e=[];_.each(_.keys(d.state_ids),function(g){var f=_.difference(d.state_ids[g],b[g]);e=e.concat(f)});if(e.length){c.updateHdas(e)}if((c.get("state")===HistoryDatasetAssociation.STATES.RUNNING)||(c.get("state")===HistoryDatasetAssociation.STATES.QUEUED)){setTimeout(function(){c.stateUpdater()},History.UPDATE_DELAY)}else{c.trigger("ready")}}).error(function(f,d,e){if(!((f.readyState===0)&&(f.status===0))){alert(_l("Error getting history updates from the server.")+"\n"+e)}})},updateHdas:function(b){var a=this;jQuery.ajax({url:this.url()+"/contents?"+jQuery.param({ids:b.join(",")}),error:function(f,c,d){var e="ERROR updating hdas from api history contents:";a.log(e,b,f,c,d);alert(e+b.join(","))},success:function(d,c,f){a.log(a+".updateHdas, success:",d,c,f);var e=[];_.each(d,function(h,i){var g=a.hdas.get(h.id);if(g){a.log("found existing model in list for id "+h.id+", updating...:");g.set(h)}else{a.log("NO existing model for id "+h.id+", creating...:");e.push(h)}});if(e.length){a.addHdas(e)}}})},addHdas:function(a){var b=this;_.each(a,function(c,d){var e=b.hdas.hidToCollectionIndex(c.hid);c.history_id=b.get("id");b.hdas.add(new HistoryDatasetAssociation(c),{at:e,silent:true})});b.hdas.trigger("add",a)},toString:function(){var a=(this.get("name"))?(","+this.get("name")):("");return"History("+this.get("id")+a+")"}});History.UPDATE_DELAY=4000;var HistoryCollection=Backbone.Collection.extend(LoggableMixin).extend({model:History,urlRoot:"api/histories"});
\ No newline at end of file
+var History=BaseModel.extend(LoggableMixin).extend({defaults:{id:"",name:"",state:"",diskSize:0,deleted:false,annotation:null,message:null},urlRoot:"api/histories/",url:function(){return"api/histories/"+this.get("id")},initialize:function(a,b){this.log(this+".initialize:",a,b);this.hdas=new HDACollection();if(b){if(_.isArray(b)){this.hdas.reset(b);this.checkForUpdates()}else{if(_.isString(b)&&(b.match(/error/i))){alert(_l("Error loading bootstrapped history")+":\n"+b)}}}},loadFromApi:function(a,c){var b=this;b.attributes.id=a;jQuery.when(jQuery.ajax("api/users/current"),b.fetch()).then(function(e,d){b.attributes.user=e[0];b.trigger("loaded:user",e[0]);b.trigger("loaded",d[0])}).then(function(){jQuery.ajax(b.url()+"/contents?"+jQuery.param({ids:b.hdaIdsFromStateIds().join(",")})).success(function(d){b.hdas.reset(d);b.checkForUpdates();b.trigger("loaded:hdas",d);if(c){callback(b)}})})},hdaIdsFromStateIds:function(){return _.reduce(_.values(this.get("state_ids")),function(b,a){return b.concat(a)})},checkForUpdates:function(a){if(this.hdas.running().length){this.stateUpdater()}else{this.trigger("ready")}return this},stateUpdater:function(){var c=this,a=this.get("state"),b=this.get("state_ids");jQuery.ajax("api/histories/"+this.get("id")).success(function(d){c.set(d);c.log("current history state:",c.get("state"),"(was)",a,"new size:",c.get("nice_size"));var e=[];_.each(_.keys(d.state_ids),function(g){var f=_.difference(d.state_ids[g],b[g]);e=e.concat(f)});if(e.length){c.fetchHdaUpdates(e)}if((c.get("state")===HistoryDatasetAssociation.STATES.RUNNING)||(c.get("state")===HistoryDatasetAssociation.STATES.QUEUED)){setTimeout(function(){c.stateUpdater()},History.UPDATE_DELAY)}else{c.trigger("ready")}}).error(function(f,d,e){if(!((f.readyState===0)&&(f.status===0))){alert(_l("Error getting history updates from the server.")+"\n"+e)}})},fetchHdaUpdates:function(b){var a=this;jQuery.ajax({url:this.url()+"/contents?"+jQuery.param({ids:b.join(",")}),error:function(h,c,d){if((h.readyState===0)&&(h.status===0)){return}var f=JSON.parse(h.responseText);if(_.isArray(f)){var e=_.groupBy(f,function(i){if(_.has(i,"error")){return"errored"}return"ok"});a.log("fetched, errored datasets:",e.errored);a.updateHdas(f)}else{var g=_l("ERROR updating hdas from api history contents")+": ";a.log(g,b,h,c,d,errorJSON);alert(g+b.join(","))}},success:function(d,c,e){a.log(a+".fetchHdaUpdates, success:",c,e);a.updateHdas(d)}})},updateHdas:function(a){var c=this,b=[];c.log(c+".updateHdas:",a);_.each(a,function(e,f){var d=c.hdas.get(e.id);if(d){c.log("found existing model in list for id "+e.id+", updating...:");d.set(e)}else{c.log("NO existing model for id "+e.id+", creating...:");b.push(e)}});if(b.length){c.addHdas(b)}},addHdas:function(a){var b=this;_.each(a,function(c,d){var e=b.hdas.hidToCollectionIndex(c.hid);c.history_id=b.get("id");b.hdas.add(new HistoryDatasetAssociation(c),{at:e,silent:true})});b.hdas.trigger("add",a)},toString:function(){var a=(this.get("name"))?(","+this.get("name")):("");return"History("+this.get("id")+a+")"}});History.UPDATE_DELAY=4000;var HistoryCollection=Backbone.Collection.extend(LoggableMixin).extend({model:History,urlRoot:"api/histories"});
\ No newline at end of file
diff -r d4d5588574ccb7faea8abfb0f0ca9fe9b48e701e -r 149f0fc73fae0494fa5cf29ec719bf38981c01b6 static/scripts/packed/viz/trackster_ui.js
--- a/static/scripts/packed/viz/trackster_ui.js
+++ b/static/scripts/packed/viz/trackster_ui.js
@@ -1,1 +1,1 @@
-define(["base","libs/underscore","viz/trackster/slotting","viz/trackster/painters","viz/trackster/tracks","viz/visualization"],function(g,c,h,e,b,d){var a=b.object_from_template;var f=g.Base.extend({initialize:function(j){this.baseURL=j},createButtonMenu:function(){var j=this,k=create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){d.select_datasets(select_datasets_url,add_track_async_url,{"f-dbkey":view.dbkey},function(l){c.each(l,function(m){view.add_drawable(a(m,view,view))})})}},{icon_class:"block--plus",title:"Add group",on_click:function(){view.add_drawable(new b.DrawableGroup(view,view,{name:"New Group"}))}},{icon_class:"bookmarks",title:"Bookmarks",on_click:function(){parent.force_right_panel(($("div#right").css("right")=="0px"?"hide":"show"))}},{icon_class:"globe",title:"Circster",on_click:function(){window.location=j.baseURL+"visualization/circster?id="+view.vis_id}},{icon_class:"disk--arrow",title:"Save",on_click:function(){show_modal("Saving...","progress");var l=[];$(".bookmark").each(function(){l.push({position:$(this).children(".position").text(),annotation:$(this).children(".annotation").text()})});var m=(view.overview_drawable?view.overview_drawable.name:null),n={view:view.to_dict(),viewport:{chrom:view.chrom,start:view.low,end:view.high,overview:m},bookmarks:l};$.ajax({url:galaxy_paths.get("visualization_url"),type:"POST",dataType:"json",data:{id:view.vis_id,title:view.name,dbkey:view.dbkey,type:"trackster",vis_json:JSON.stringify(n)}}).success(function(o){hide_modal();view.vis_id=o.vis_id;view.has_changes=false;window.history.pushState({},"",o.url+window.location.hash)}).error(function(){show_modal("Could Not Save","Could not save visualization. Please try again later.",{Close:hide_modal})})}},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location=j.baseURL+"visualization/list"}}],{tooltip_config:{placement:"bottom"}});this.buttonMenu=k;return k},add_bookmarks:function(){var j=this,k=this.baseURL;show_modal("Select dataset for new bookmarks","progress");$.ajax({url:this.baseURL+"/visualization/list_histories",data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(l){show_modal("Select dataset for new bookmarks",l,{Cancel:function(){hide_modal()},Insert:function(){$("input[name=id]:checked,input[name=ldda_ids]:checked").first().each(function(){var m,n=$(this).val();if($(this).attr("name")==="id"){m={hda_id:n}}else{m={ldda_id:n}}$.ajax({url:this.baseURL+"/visualization/bookmarks_from_dataset",data:m,dataType:"json"}).then(function(o){for(i=0;i<o.data.length;i++){var p=o.data[i];j.add_bookmark(p[0],p[1])}})});hide_modal()}})}})},add_bookmark:function(n,l,j){var p=$("#bookmarks-container"),r=$("<div/>").addClass("bookmark").appendTo(p);var s=$("<div/>").addClass("position").appendTo(r),o=$("<a href=''/>").text(n).appendTo(s).click(function(){view.go_to(n);return false}),m=$("<div/>").text(l).appendTo(r);if(j){var q=$("<div/>").addClass("delete-icon-container").prependTo(r).click(function(){r.slideUp("fast");r.remove();view.has_changes=true;return false}),k=$("<a href=''/>").addClass("icon-button delete").appendTo(q);m.make_text_editable({num_rows:3,use_textarea:true,help_text:"Edit bookmark note"}).addClass("annotation")}view.has_changes=true;return r},create_visualization:function(o,j,n,p,m){var l=this,k=new b.TracksterView(o);k.editor=true;$.when(k.load_chroms_deferred).then(function(A){if(j){var y=j.chrom,q=j.start,v=j.end,s=j.overview;if(y&&(q!==undefined)&&v){k.change_chrom(y,q,v)}}else{k.change_chrom(A[0].chrom)}if(n){var t,r,u;for(var w=0;w<n.length;w++){k.add_drawable(a(n[w],k,k))}}k.update_intro_div();var z;for(var w=0;w<k.drawables.length;w++){if(k.drawables[w].name===s){k.set_overview(k.drawables[w]);break}}if(p){var x;for(var w=0;w<p.length;w++){x=p[w];l.add_bookmark(x.position,x.annotation,m)}}k.has_changes=false});return k},init_keyboard_nav:function(j){$(document).keydown(function(k){if($(k.srcElement).is(":input")){return}switch(k.which){case 37:j.move_fraction(0.25);break;case 38:var l=Math.round(j.viewport_container.height()/15);j.viewport_container.scrollTop(j.viewport_container.scrollTop()-20);break;case 39:j.move_fraction(-0.25);break;case 40:var l=Math.round(j.viewport_container.height()/15);j.viewport_container.scrollTop(j.viewport_container.scrollTop()+20);break}})}});return{object_from_template:a,TracksterUI:f}});
\ No newline at end of file
+define(["base","libs/underscore","viz/trackster/slotting","viz/trackster/painters","viz/trackster/tracks","viz/visualization"],function(g,c,h,e,b,d){var a=b.object_from_template;var f=g.Base.extend({initialize:function(j){this.baseURL=j},createButtonMenu:function(){var j=this,k=create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){d.select_datasets(select_datasets_url,add_track_async_url,{"f-dbkey":view.dbkey},function(l){c.each(l,function(m){view.add_drawable(a(m,view,view))})})}},{icon_class:"block--plus",title:"Add group",on_click:function(){view.add_drawable(new b.DrawableGroup(view,view,{name:"New Group"}))}},{icon_class:"bookmarks",title:"Bookmarks",on_click:function(){parent.force_right_panel(($("div#right").css("right")=="0px"?"hide":"show"))}},{icon_class:"globe",title:"Circster",on_click:function(){window.location=j.baseURL+"visualization/circster?id="+view.vis_id}},{icon_class:"disk--arrow",title:"Save",on_click:function(){show_modal("Saving...","progress");var l=[];$(".bookmark").each(function(){l.push({position:$(this).children(".position").text(),annotation:$(this).children(".annotation").text()})});var m=(view.overview_drawable?view.overview_drawable.name:null),n={view:view.to_dict(),viewport:{chrom:view.chrom,start:view.low,end:view.high,overview:m},bookmarks:l};$.ajax({url:galaxy_paths.get("visualization_url"),type:"POST",dataType:"json",data:{id:view.vis_id,title:view.name,dbkey:view.dbkey,type:"trackster",vis_json:JSON.stringify(n)}}).success(function(o){hide_modal();view.vis_id=o.vis_id;view.has_changes=false;window.history.pushState({},"",o.url+window.location.hash)}).error(function(){show_modal("Could Not Save","Could not save visualization. Please try again later.",{Close:hide_modal})})}},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location=j.baseURL+"visualization/list"}}],{tooltip_config:{placement:"bottom"}});this.buttonMenu=k;return k},add_bookmarks:function(){var j=this,k=this.baseURL;show_modal("Select dataset for new bookmarks","progress");$.ajax({url:this.baseURL+"/visualization/list_histories",data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(l){show_modal("Select dataset for new bookmarks",l,{Cancel:function(){hide_modal()},Insert:function(){$("input[name=id]:checked,input[name=ldda_ids]:checked").first().each(function(){var m,n=$(this).val();if($(this).attr("name")==="id"){m={hda_id:n}}else{m={ldda_id:n}}$.ajax({url:this.baseURL+"/visualization/bookmarks_from_dataset",data:m,dataType:"json"}).then(function(o){for(i=0;i<o.data.length;i++){var p=o.data[i];j.add_bookmark(p[0],p[1])}})});hide_modal()}})}})},add_bookmark:function(n,l,j){var p=$("#bookmarks-container"),r=$("<div/>").addClass("bookmark").appendTo(p);var s=$("<div/>").addClass("position").appendTo(r),o=$("<a href=''/>").text(n).appendTo(s).click(function(){view.go_to(n);return false}),m=$("<div/>").text(l).appendTo(r);if(j){var q=$("<div/>").addClass("delete-icon-container").prependTo(r).click(function(){r.slideUp("fast");r.remove();view.has_changes=true;return false}),k=$("<a href=''/>").addClass("icon-button delete").appendTo(q);m.make_text_editable({num_rows:3,use_textarea:true,help_text:"Edit bookmark note"}).addClass("annotation")}view.has_changes=true;return r},create_visualization:function(o,j,n,p,m){var l=this,k=new b.TracksterView(o);k.editor=true;$.when(k.load_chroms_deferred).then(function(A){if(j){var y=j.chrom,q=j.start,v=j.end,s=j.overview;if(y&&(q!==undefined)&&v){k.change_chrom(y,q,v)}else{k.change_chrom(A[0].chrom)}}else{k.change_chrom(A[0].chrom)}if(n){var t,r,u;for(var w=0;w<n.length;w++){k.add_drawable(a(n[w],k,k))}}k.update_intro_div();var z;for(var w=0;w<k.drawables.length;w++){if(k.drawables[w].name===s){k.set_overview(k.drawables[w]);break}}if(p){var x;for(var w=0;w<p.length;w++){x=p[w];l.add_bookmark(x.position,x.annotation,m)}}k.has_changes=false});return k},init_keyboard_nav:function(j){$(document).keydown(function(k){if($(k.srcElement).is(":input")){return}switch(k.which){case 37:j.move_fraction(0.25);break;case 38:var l=Math.round(j.viewport_container.height()/15);j.viewport_container.scrollTop(j.viewport_container.scrollTop()-20);break;case 39:j.move_fraction(-0.25);break;case 40:var l=Math.round(j.viewport_container.height()/15);j.viewport_container.scrollTop(j.viewport_container.scrollTop()+20);break}})}});return{object_from_template:a,TracksterUI:f}});
\ No newline at end of file
diff -r d4d5588574ccb7faea8abfb0f0ca9fe9b48e701e -r 149f0fc73fae0494fa5cf29ec719bf38981c01b6 templates/grid_base.mako
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -52,23 +52,8 @@
</%def><%def name="grid_javascripts()">
- ${h.js("libs/jquery/jquery.autocomplete", "galaxy.autocom_tagging", "libs/jquery/jquery.rating" )}
+ ${h.js("libs/jquery/jquery.autocomplete", "galaxy.autocom_tagging", "libs/jquery/jquery.rating", "galaxy.grids" )}
<script type="text/javascript">
- // This is necessary so that, when nested arrays are used in ajax/post/get methods, square brackets ('[]') are
- // not appended to the identifier of a nested array.
- jQuery.ajaxSettings.traditional = true;
-
- ## TODO: generalize and move into galaxy.base.js
- $(document).ready(function() {
- init_grid_elements();
- init_grid_controls();
-
- // Initialize text filters to select text on click and use normal font when user is typing.
- $('input[type=text]').each(function() {
- $(this).click(function() { $(this).select(); } )
- .keyup(function () { $(this).css("font-style", "normal"); })
- });
- });
## TODO: Can this be moved into base.mako? Also, this is history-specific grid code.
%if refresh_frames:
%if 'masthead' in refresh_frames:
@@ -90,7 +75,7 @@
}
else {
// TODO: redirecting to root should be done on the server side so that page
- // doesn't have to load.
+ // does not have to load.
// No history frame, so refresh to root to see history.
window.top.location.href = "${h.url_for( controller='root' )}";
@@ -105,146 +90,21 @@
}
%endif
%endif
-
+
+ // Needed URLs for grid history searching.
+ var history_tag_autocomplete_url = "${h.url_for( controller='tag', action='tag_autocomplete_data', item_class='History' )}",
+ history_name_autocomplete_url = "${h.url_for( controller='history', action='name_autocomplete_data' )}";
+
//
- // Code to handle grid operations: filtering, sorting, paging, and operations.
+ // Create grid object.
//
-
+
// Operations that are async (AJAX) compatible.
- var async_ops = {};
+ var async_ops = [];
%for operation in [op for op in grid.operations if op.async_compatible]:
- async_ops['${operation.label.lower()}'] = "True";
+ async_ops.push('${operation.label.lower()}');
%endfor
-
- // Init operation buttons.
- function init_operation_buttons() {
- // Initialize operation buttons.
- $('input[name=operation]:submit').each(function() {
- $(this).click( function() {
- var webapp = $("input[name=webapp]").attr("value");
- var operation_name = $(this).val();
- // For some reason, $('input[name=id]:checked').val() does not return all ids for checked boxes.
- // The code below performs this function.
- var item_ids = [];
- $('input[name=id]:checked').each(function() {
- item_ids.push( $(this).val() );
- });
- do_operation(webapp, operation_name, item_ids);
- });
- });
- };
-
- // Initialize grid controls
- function init_grid_controls() {
- init_operation_buttons();
-
- // Initialize submit image elements.
- $('.submit-image').each( function() {
- // On mousedown, add class to simulate click.
- $(this).mousedown( function() {
- $(this).addClass('gray-background');
- });
-
- // On mouseup, add class to simulate click.
- $(this).mouseup( function() {
- $(this).removeClass('gray-background');
- });
- });
-
- // Initialize sort links.
- $('.sort-link').each( function() {
- $(this).click( function() {
- set_sort_condition( $(this).attr('sort_key') );
- return false;
- });
- });
-
- // Initialize page links.
- $('.page-link > a').each( function() {
- $(this).click( function() {
- set_page( $(this).attr('page_num') );
- return false;
- });
- });
- // Initialize categorical filters.
- $('.categorical-filter > a').each( function() {
- $(this).click( function() {
- set_categorical_filter( $(this).attr('filter_key'), $(this).attr('filter_val') );
- return false;
- });
- });
-
- // Initialize text filters.
- $('.text-filter-form').each( function() {
- $(this).submit( function() {
- var column_key = $(this).attr('column_key');
- var text_input_obj = $('#input-' + column_key + '-filter');
- var text_input = text_input_obj.val();
- text_input_obj.val('');
- add_filter_condition(column_key, text_input, true);
- return false;
- });
- });
-
- // Initialize autocomplete for text inputs in search UI.
- var t = $("#input-tags-filter");
- if (t.length) {
- t.autocomplete( "${h.url_for( controller='tag', action='tag_autocomplete_data', item_class='History' )}",
- { selectFirst: false, autoFill: false, highlight: false, mustMatch: false });
- }
-
- var t2 = $("#input-name-filter");
- if (t2.length) {
- t2.autocomplete( "${h.url_for( controller='history', action='name_autocomplete_data' )}",
- { selectFirst: false, autoFill: false, highlight: false, mustMatch: false });
- }
-
- // Initialize standard, advanced search toggles.
- $('.advanced-search-toggle').each( function() {
- $(this).click( function() {
- $("#standard-search").slideToggle('fast');
- $('#advanced-search').slideToggle('fast');
- return false;
- });
- });
- }
-
- // Initialize grid elements.
- function init_grid_elements() {
- // Initialize grid selection checkboxes.
- $(".grid").each( function() {
- var checkboxes = $(this).find("input.grid-row-select-checkbox");
- var check_count = $(this).find("span.grid-selected-count");
- var update_checked = function() {
- check_count.text( $(checkboxes).filter(":checked").length );
- };
-
- $(checkboxes).each( function() {
- $(this).change(update_checked);
- });
- update_checked();
- });
-
- // Initialize item labels.
- $(".label").each( function() {
- // If href has an operation in it, do operation when clicked. Otherwise do nothing.
- var href = $(this).attr('href');
- if ( href !== undefined && href.indexOf('operation=') != -1 ) {
- $(this).click( function() {
- do_operation_from_href( $(this).attr('href') );
- return false;
- });
- }
- });
-
- // Initialize ratings.
- $('.community_rating_star').rating({});
-
- // Initialize item menu operations.
- make_popup_menus();
- }
-
// Filter values for categorical filters.
var categorical_filters = {};
%for column in grid.columns:
@@ -253,367 +113,22 @@
categorical_filters['${column.key}'] = ${column.key}_filters;
%endif
%endfor
-
- // Initialize URL args with filter arguments.
- var url_args_init = ${h.to_json_string( cur_filter_dict )},
- url_args = {};
-
- // Place "f-" in front of all filter arguments.
-
- for (arg in url_args_init) {
- url_args["f-" + arg] = url_args_init[arg];
- }
-
- // Add sort argument to URL args.
- url_args['sort'] = "${sort_key}";
-
- // Add show_item_checkboxes argument to URL args.
- url_args['show_item_checkboxes'] = ("${context.get('show_item_checkboxes', False)}" === "True");
-
- // Add async keyword to URL args.
- url_args['async'] = true;
-
- // Add page to URL args.
- url_args['page'] = ${cur_page_num};
-
- var num_pages = ${num_pages};
-
- // Go back to page one; this is useful when a filter is applied.
- function go_page_one() {
- // Need to go back to page 1 if not showing all.
- var cur_page = url_args['page'];
- if (cur_page !== null && cur_page !== undefined && cur_page != 'all') {
- url_args['page'] = 1;
- }
- }
-
- // Add a condition to the grid filter; this adds the condition and refreshes the grid.
- function add_filter_condition(name, value, append) {
- // Do nothing is value is empty.
- if (value == "") {
- return false;
- }
-
- // Update URL arg with new condition.
- if (append) {
- // Update or append value.
- var cur_val = url_args["f-" + name];
- var new_val;
- if (cur_val === null || cur_val === undefined) {
- new_val = value;
- } else if (typeof(cur_val) == "string") {
- if (cur_val == "All") {
- new_val = value;
- } else {
- // Replace string with array.
- var values = [];
- values[0] = cur_val;
- values[1] = value;
- new_val = values;
- }
- } else {
- // Current value is an array.
- new_val = cur_val;
- new_val[new_val.length] = value;
- }
- url_args["f-" + name] = new_val;
- } else {
- // Replace value.
- url_args["f-" + name] = value;
- }
-
- // Add button that displays filter and provides a button to delete it.
- var t = $("<span>" + value + "<a href='javascript:void(0);'><span class='delete-search-icon' /></a></span>");
- t.addClass('text-filter-val');
- t.click(function() {
- // Remove filter condition.
-
- // Remove visible element.
- $(this).remove();
-
- // Remove condition from URL args.
- var cur_val = url_args["f-" + name];
- if (cur_val === null || cur_val === undefined) {
- // Unexpected. Throw error?
- } else if (typeof(cur_val) == "string") {
- if (cur_val == "All") {
- // Unexpected. Throw error?
- } else {
- // Remove condition.
- delete url_args["f-" + name];
- }
- } else {
- // Current value is an array.
- var conditions = cur_val;
- for (var index = 0; index < conditions.length; index++) {
- if (conditions[index] == value) {
- conditions.splice(index, 1);
- break;
- }
- }
- }
-
- go_page_one();
- update_grid();
- });
-
- var container = $('#' + name + "-filtering-criteria");
- container.append(t);
-
- go_page_one();
- update_grid();
- }
-
- // Add tag to grid filter.
- function add_tag_to_grid_filter(tag_name, tag_value) {
- // Put tag name and value together.
- var tag = tag_name + (tag_value !== undefined && tag_value != "" ? ":" + tag_value : "");
- $('#advanced-search').show('fast');
- add_filter_condition("tags", tag, true);
- }
-
- // Set sort condition for grid.
- function set_sort_condition(col_key) {
- // Set new sort condition. New sort is col_key if sorting new column; if reversing sort on
- // currently sorted column, sort is reversed.
- var cur_sort = url_args['sort'];
- var new_sort = col_key;
- if ( cur_sort.indexOf( col_key ) != -1) {
- // Reverse sort.
- if ( cur_sort.substring(0,1) != '-' ) {
- new_sort = '-' + col_key;
- } else {
- // Sort reversed by using just col_key.
- }
- }
-
- // Remove sort arrows elements.
- $('.sort-arrow').remove();
-
- // Add sort arrow element to new sort column.
- var sort_arrow = (new_sort.substring(0,1) == '-') ? "↑" : "↓";
- var t = $("<span>" + sort_arrow + "</span>").addClass('sort-arrow');
- var th = $("#" + col_key + '-header');
- th.append(t);
-
- // Need to go back to page 1 if not showing all.
- var cur_page = url_args['page'];
- if (cur_page !== null && cur_page !== undefined && cur_page != 'all') {
- url_args['page'] = 1;
- }
- // Update grid.
- url_args['sort'] = new_sort;
- go_page_one();
- update_grid();
- }
-
- // Set new value for categorical filter.
- function set_categorical_filter(name, new_value) {
- // Update filter hyperlinks to reflect new filter value.
- var category_filter = categorical_filters[name];
- var cur_value = url_args["f-" + name];
- $("." + name + "-filter").each( function() {
- var text = $.trim( $(this).text() );
- var filter = category_filter[text];
- var filter_value = filter[name];
- if (filter_value == new_value) {
- // Remove filter link since grid will be using this filter. It is assumed that
- // this element has a single child, a hyperlink/anchor with text.
- $(this).empty();
- $(this).addClass("current-filter");
- $(this).append(text);
- } else if (filter_value == cur_value) {
- // Add hyperlink for this filter since grid will no longer be using this filter. It is assumed that
- // this element has a single child, a hyperlink/anchor.
- $(this).empty();
- var t = $("<a href='#'>" + text + "</a>");
- t.click(function() {
- set_categorical_filter( name, filter_value );
- });
- $(this).removeClass("current-filter");
- $(this).append(t);
- }
- });
-
- // Update grid.
- url_args["f-" + name] = new_value;
- go_page_one();
- update_grid();
- }
-
- // Set page to view.
- function set_page(new_page) {
- // Update page hyperlink to reflect new page.
- $(".page-link").each( function() {
- var id = $(this).attr('id');
- var page_num = parseInt( id.split("-")[2] ); // Id has form 'page-link-<page_num>
- var cur_page = url_args['page'];
- if (page_num == new_page) {
- // Remove link to page since grid will be on this page. It is assumed that
- // this element has a single child, a hyperlink/anchor with text.
- var text = $(this).children().text();
- $(this).empty();
- $(this).addClass("inactive-link");
- $(this).text(text);
- } else if (page_num == cur_page) {
- // Add hyperlink to this page since grid will no longer be on this page. It is assumed that
- // this element has a single child, a hyperlink/anchor.
- var text = $(this).text();
- $(this).empty();
- $(this).removeClass("inactive-link");
- var t = $("<a href='#'>" + text + "</a>");
- t.click(function() {
- set_page(page_num);
- });
- $(this).append(t);
- }
- });
-
- var maintain_page_links = true;
- if (new_page == "all") {
- url_args['page'] = new_page;
- maintain_page_links = false;
- } else {
- url_args['page'] = parseInt(new_page);
- }
- update_grid(maintain_page_links);
- }
-
- // Perform a grid operation.
- function do_operation(webapp, operation, item_ids) {
- operation = operation.toLowerCase();
-
- // Update URL args.
- url_args["webapp"] = webapp;
- url_args["operation"] = operation;
- url_args["id"] = item_ids;
-
- // If operation cannot be performed asynchronously, redirect to location. Otherwise do operation.
- var no_async = ( async_ops[operation] === undefined || async_ops[operation] === null);
- if (no_async) {
- go_to_URL();
- } else {
- update_grid(true);
- delete url_args['webapp'];
- delete url_args['operation'];
- delete url_args['id'];
- }
- }
-
- // Perform a hyperlink click that initiates an operation. If there is no operation, ignore click.
- function do_operation_from_href(href) {
- // Get operation, id in hyperlink's href.
- var href_parts = href.split("?");
- if (href_parts.length > 1) {
- var href_parms_str = href_parts[1];
- var href_parms = href_parms_str.split("&");
- var operation = null;
- var id = -1;
- var webapp = 'galaxy';
- for (var index = 0; index < href_parms.length; index++) {
- if (href_parms[index].indexOf('operation') != -1) {
- // Found operation parm; get operation value.
- operation = href_parms[index].split('=')[1];
- } else if (href_parms[index].indexOf('id') != -1) {
- // Found id parm; get id value.
- id = href_parms[index].split('=')[1];
- } else if (href_parms[index].indexOf('webapp') != -1) {
- // Found webapp parm; get webapp value.
- webapp = href_parms[index].split('=')[1];
- }
- }
- // Do operation.
- do_operation(webapp, operation, id);
- return false;
- }
- }
-
- // Navigate window to the URL defined by url_args. This method should be used to short-circuit grid AJAXing.
- function go_to_URL() {
- // Not async request.
- url_args['async'] = false;
-
- // Build argument string.
- var arg_str = "";
- for (var arg in url_args) {
- arg_str = arg_str + arg + "=" + url_args[arg] + "&";
- }
-
- // Go.
- window.location = encodeURI( "${h.url_for()}?" + arg_str );
- }
-
- // Update grid.
- function update_grid(maintain_page_links) {
- ## If grid is not using async, then go to URL.
- %if not grid.use_async:
- go_to_URL();
- return;
- %endif
-
- // If there's an operation in the args, do POST; otherwise, do GET.
- var operation = url_args['operation'];
- var method = (operation !== null && operation !== undefined ? "POST" : "GET" );
- $('.loading-elt-overlay').show(); // Show overlay to indicate loading and prevent user actions.
- $.ajax({
- type: method,
- url: "${h.url_for()}",
- data: url_args,
- error: function() { alert( "Grid refresh failed" ); },
- success: function(response_text) {
- // HACK: use a simple string to separate the elements in the
- // response: (1) table body; (2) number of pages in table; and (3) message.
- var parsed_response_text = response_text.split("*****");
-
- // Update grid body and footer.
- $('#grid-table-body').html(parsed_response_text[0]);
- // FIXME: this does not work at all; what's needed is a function
- // that updates page links when number of pages changes.
- $('#grid-table-footer').html(parsed_response_text[1]);
-
- // Trigger custom event to indicate grid body has changed.
- $('#grid-table-body').trigger('update');
-
- // Init grid.
- init_grid_elements();
- init_operation_buttons();
- make_popup_menus();
-
- // Hide loading overlay.
- $('.loading-elt-overlay').hide();
-
- // Show message if there is one.
- var message = $.trim( parsed_response_text[2] );
- if (message != "") {
- $('#grid-message').html( message ).show();
- setTimeout( function() { $('#grid-message').hide(); }, 5000);
- }
- }
- });
- }
-
- function check_all_items() {
- var chk_all = document.getElementById('check_all');
- var checks = document.getElementsByTagName('input');
- //var boxLength = checks.length;
- var total = 0;
- if ( chk_all.checked == true ) {
- for ( i=0; i < checks.length; i++ ) {
- if ( checks[i].name.indexOf( 'id' ) != -1) {
- checks[i].checked = true;
- total++;
- }
- }
- }
- else {
- for ( i=0; i < checks.length; i++ ) {
- if ( checks[i].name.indexOf( 'id' ) != -1) {
- checks[i].checked = false
- }
- }
- }
- init_grid_elements();
- }
+
+ /** Returns true if string denotes true. */
+ var is_true = function(s) { return _.indexOf(['True', 'true', 't'], s) !== -1; };
+
+ // Create grid.
+ var grid = new Grid({
+ url_base: '${h.url_for()}',
+ async: is_true('${grid.use_async}'),
+ async_ops: async_ops,
+ categorical_filters: categorical_filters,
+ filters: ${h.to_json_string( cur_filter_dict )},
+ sort_key: '${sort_key}',
+ show_item_checkboxes: is_true('${context.get('show_item_checkboxes', False)}'),
+ cur_page: ${cur_page_num},
+ num_pages: ${num_pages}
+ });
</script></%def>
@@ -700,7 +215,6 @@
show_item_checkboxes = True
%><form action="${url()}" method="post" onsubmit="return false;">
- <input type="hidden" name="webapp" value="${webapp}"/><table id="grid-table" class="grid"><thead id="grid-table-header"><tr>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5315471299a9/
changeset: 5315471299a9
user: kellrott
date: 2013-01-10 20:46:20
summary: Adding UUIDType to data model and uuid column to dataset table.
affected #: 4 files
diff -r c015b82b3944f967e2c859d5552c00e3e38a2da0 -r 5315471299a992d4fd243fbb681e5caf65ff2092 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -895,6 +895,7 @@
self.external_filename = external_filename
self._extra_files_path = extra_files_path
self.file_size = file_size
+ self.uuid = None
def get_file_name( self ):
if not self.external_filename:
diff -r c015b82b3944f967e2c859d5552c00e3e38a2da0 -r 5315471299a992d4fd243fbb681e5caf65ff2092 lib/galaxy/model/custom_types.py
--- a/lib/galaxy/model/custom_types.py
+++ b/lib/galaxy/model/custom_types.py
@@ -1,9 +1,11 @@
from sqlalchemy.types import *
+
import pkg_resources
pkg_resources.require("simplejson")
import simplejson
import pickle
import copy
+import uuid
import binascii
from galaxy.util.bunch import Bunch
from galaxy.util.aliaspickler import AliasPickleModule
@@ -84,6 +86,39 @@
ret = None
return ret
+
+
+class UUIDType(TypeDecorator):
+ """
+ Platform-independent UUID type.
+
+ Based on http://docs.sqlalchemy.org/en/rel_0_8/core/types.html#backend-agnostic-guid…
+ Changed to remove sqlalchemy 0.8 specific code
+
+ CHAR(32), storing as stringified hex values.
+ """
+ impl = CHAR
+
+ def load_dialect_impl(self, dialect):
+ return dialect.type_descriptor(CHAR(32))
+
+ def process_bind_param(self, value, dialect):
+ if value is None:
+ return value
+ else:
+ if not isinstance(value, uuid.UUID):
+ return "%.32x" % uuid.UUID(value)
+ else:
+ # hexstring
+ return "%.32x" % value
+
+ def process_result_value(self, value, dialect):
+ if value is None:
+ return value
+ else:
+ return uuid.UUID(value)
+
+
class TrimmedString( TypeDecorator ):
impl = String
def process_bind_param( self, value, dialect ):
diff -r c015b82b3944f967e2c859d5552c00e3e38a2da0 -r 5315471299a992d4fd243fbb681e5caf65ff2092 lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py
+++ b/lib/galaxy/model/mapping.py
@@ -135,7 +135,8 @@
Column( "external_filename" , TEXT ),
Column( "_extra_files_path", TEXT ),
Column( 'file_size', Numeric( 15, 0 ) ),
- Column( 'total_size', Numeric( 15, 0 ) ) )
+ Column( 'total_size', Numeric( 15, 0 ) ),
+ Column( 'uuid', UUIDType() ) )
HistoryDatasetAssociationDisplayAtAuthorization.table = Table( "history_dataset_association_display_at_authorization", metadata,
Column( "id", Integer, primary_key=True ),
diff -r c015b82b3944f967e2c859d5552c00e3e38a2da0 -r 5315471299a992d4fd243fbb681e5caf65ff2092 lib/galaxy/model/migrate/versions/0110_add_dataset_uuid.py
--- /dev/null
+++ b/lib/galaxy/model/migrate/versions/0110_add_dataset_uuid.py
@@ -0,0 +1,50 @@
+"""
+Add UUID column to dataset table
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+from galaxy.model.custom_types import UUIDType
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData( migrate_engine )
+#db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
+
+dataset_uuid_column = Column( "uuid", UUIDType, nullable=True )
+
+
+def display_migration_details():
+ print ""
+ print "This migration adds uuid column to dataset table"
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+
+ # Add the uuid colum to the dataset table
+ try:
+ dataset_table = Table( "dataset", metadata, autoload=True )
+ dataset_uuid_column.create( dataset_table )
+ assert dataset_uuid_column is dataset_table.c.uuid
+ except Exception, e:
+ print str(e)
+ log.error( "Adding column 'uuid' to dataset table failed: %s" % str( e ) )
+ return
+
+
+def downgrade():
+ metadata.reflect()
+
+ # Drop the Job table's exit_code column.
+ try:
+ dataset_table = Table( "dataset", metadata, autoload=True )
+ dataset_uuid = dataset_table.c.uuid
+ dataset_uuid.drop()
+ except Exception, e:
+ log.debug( "Dropping 'uuid' column from dataset table failed: %s" % ( str( e ) ) )
+
+
https://bitbucket.org/galaxy/galaxy-central/commits/d4d5588574cc/
changeset: d4d5588574cc
user: dannon
date: 2013-01-28 19:56:01
summary: Merged in kellrott/galaxy-central (pull request #105)
Adding UUIDType to data model and uuid column to dataset table.
affected #: 4 files
diff -r b1a778e027ff330f044d44ca0ba1a07992d376b4 -r d4d5588574ccb7faea8abfb0f0ca9fe9b48e701e lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -895,6 +895,7 @@
self.external_filename = external_filename
self._extra_files_path = extra_files_path
self.file_size = file_size
+ self.uuid = None
def get_file_name( self ):
if not self.external_filename:
diff -r b1a778e027ff330f044d44ca0ba1a07992d376b4 -r d4d5588574ccb7faea8abfb0f0ca9fe9b48e701e lib/galaxy/model/custom_types.py
--- a/lib/galaxy/model/custom_types.py
+++ b/lib/galaxy/model/custom_types.py
@@ -1,9 +1,11 @@
from sqlalchemy.types import *
+
import pkg_resources
pkg_resources.require("simplejson")
import simplejson
import pickle
import copy
+import uuid
import binascii
from galaxy.util.bunch import Bunch
from galaxy.util.aliaspickler import AliasPickleModule
@@ -84,6 +86,39 @@
ret = None
return ret
+
+
+class UUIDType(TypeDecorator):
+ """
+ Platform-independent UUID type.
+
+ Based on http://docs.sqlalchemy.org/en/rel_0_8/core/types.html#backend-agnostic-guid…
+ Changed to remove sqlalchemy 0.8 specific code
+
+ CHAR(32), storing as stringified hex values.
+ """
+ impl = CHAR
+
+ def load_dialect_impl(self, dialect):
+ return dialect.type_descriptor(CHAR(32))
+
+ def process_bind_param(self, value, dialect):
+ if value is None:
+ return value
+ else:
+ if not isinstance(value, uuid.UUID):
+ return "%.32x" % uuid.UUID(value)
+ else:
+ # hexstring
+ return "%.32x" % value
+
+ def process_result_value(self, value, dialect):
+ if value is None:
+ return value
+ else:
+ return uuid.UUID(value)
+
+
class TrimmedString( TypeDecorator ):
impl = String
def process_bind_param( self, value, dialect ):
diff -r b1a778e027ff330f044d44ca0ba1a07992d376b4 -r d4d5588574ccb7faea8abfb0f0ca9fe9b48e701e lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py
+++ b/lib/galaxy/model/mapping.py
@@ -135,7 +135,8 @@
Column( "external_filename" , TEXT ),
Column( "_extra_files_path", TEXT ),
Column( 'file_size', Numeric( 15, 0 ) ),
- Column( 'total_size', Numeric( 15, 0 ) ) )
+ Column( 'total_size', Numeric( 15, 0 ) ),
+ Column( 'uuid', UUIDType() ) )
HistoryDatasetAssociationDisplayAtAuthorization.table = Table( "history_dataset_association_display_at_authorization", metadata,
Column( "id", Integer, primary_key=True ),
diff -r b1a778e027ff330f044d44ca0ba1a07992d376b4 -r d4d5588574ccb7faea8abfb0f0ca9fe9b48e701e lib/galaxy/model/migrate/versions/0110_add_dataset_uuid.py
--- /dev/null
+++ b/lib/galaxy/model/migrate/versions/0110_add_dataset_uuid.py
@@ -0,0 +1,50 @@
+"""
+Add UUID column to dataset table
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+from galaxy.model.custom_types import UUIDType
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData( migrate_engine )
+#db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
+
+dataset_uuid_column = Column( "uuid", UUIDType, nullable=True )
+
+
+def display_migration_details():
+ print ""
+ print "This migration adds uuid column to dataset table"
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+
+ # Add the uuid colum to the dataset table
+ try:
+ dataset_table = Table( "dataset", metadata, autoload=True )
+ dataset_uuid_column.create( dataset_table )
+ assert dataset_uuid_column is dataset_table.c.uuid
+ except Exception, e:
+ print str(e)
+ log.error( "Adding column 'uuid' to dataset table failed: %s" % str( e ) )
+ return
+
+
+def downgrade():
+ metadata.reflect()
+
+ # Drop the Job table's exit_code column.
+ try:
+ dataset_table = Table( "dataset", metadata, autoload=True )
+ dataset_uuid = dataset_table.c.uuid
+ dataset_uuid.drop()
+ except Exception, e:
+ log.debug( "Dropping 'uuid' column from dataset table failed: %s" % ( str( e ) ) )
+
+
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/cfdcd1bd7681/
changeset: cfdcd1bd7681
user: Kyle Ellrott
date: 2012-12-01 00:32:47
summary: Adding handler for httpexceptions.HTTPFound, so that the redirect tool will work (rather then causing an error)
affected #: 1 file
diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r cfdcd1bd7681ddb38fb4d71fcdedd5ebaf1385b6 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -36,6 +36,8 @@
from galaxy.util.shed_util_common import *
from galaxy.web import url_for
+from paste import httpexceptions
+
from galaxy.visualization.genome.visual_analytics import TracksterConfig
log = logging.getLogger( __name__ )
@@ -1790,6 +1792,9 @@
elif state.page == self.last_page:
try:
_, out_data = self.execute( trans, incoming=params, history=history )
+ except httpexceptions.HTTPFound, e:
+ #if it's a paste redirect exception, pass it up the stack
+ raise e
except Exception, e:
log.exception('Exception caught while attempting tool execution:')
return 'message.mako', dict( status='error', message='Error executing tool: %s' % str(e), refresh_frames=[] )
https://bitbucket.org/galaxy/galaxy-central/commits/b1a778e027ff/
changeset: b1a778e027ff
user: dannon
date: 2013-01-28 18:57:28
summary: Merged in kellrott/galaxy-central (pull request #92)
Adding handler for httpexceptions.HTTPFound, so that the redirect tool will work (rather then causing an error)
affected #: 1 file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: Kyle Ellrott: Adding handler for httpexceptions.HTTPFound, so that the redirect tool will work (rather then causing an error)
by Bitbucket 28 Jan '13
by Bitbucket 28 Jan '13
28 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f6ab35e84116/
changeset: f6ab35e84116
user: Kyle Ellrott
date: 2012-12-01 00:32:47
summary: Adding handler for httpexceptions.HTTPFound, so that the redirect tool will work (rather then causing an error)
affected #: 1 file
diff -r 70d52f421c7fc8edef571ad93726dbc474c35211 -r f6ab35e841165d113b1b63633e80db8d98e48b17 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -35,6 +35,8 @@
import galaxy.util.shed_util_common
from galaxy.web import url_for
+from paste import httpexceptions
+
from galaxy.visualization.genome.visual_analytics import TracksterConfig
log = logging.getLogger( __name__ )
@@ -1801,6 +1803,9 @@
elif state.page == self.last_page:
try:
_, out_data = self.execute( trans, incoming=params, history=history )
+ except httpexceptions.HTTPFound, e:
+ #if it's a paste redirect exception, pass it up the stack
+ raise e
except Exception, e:
log.exception('Exception caught while attempting tool execution:')
return 'message.mako', dict( status='error', message='Error executing tool: %s' % str(e), refresh_frames=[] )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: joachimjacob: Changed wording from unpause to resume, in accordance with corresponding history menu item.
by Bitbucket 28 Jan '13
by Bitbucket 28 Jan '13
28 Jan '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/70d52f421c7f/
changeset: 70d52f421c7f
user: joachimjacob
date: 2013-01-28 16:46:12
summary: Changed wording from unpause to resume, in accordance with corresponding history menu item.
affected #: 1 file
diff -r 18d528947af20aca02f105722a844d32f90fa0ec -r 70d52f421c7fc8edef571ad93726dbc474c35211 static/scripts/mvc/dataset/hda-base.js
--- a/static/scripts/mvc/dataset/hda-base.js
+++ b/static/scripts/mvc/dataset/hda-base.js
@@ -426,7 +426,7 @@
* @param {jQuery} parent DOM to which to append this body
*/
_render_body_paused: function( parent ){
- parent.append( $( '<div>' + _l( 'Job is paused. Use the history menu to unpause' ) + '.</div>' ) );
+ parent.append( $( '<div>' + _l( 'Job is paused. Use the history menu to resume' ) + '.</div>' ) );
parent.append( this._render_primaryActionButtons( this.defaultPrimaryActionButtonRenderers ));
},
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/853b1da64f4d/
changeset: 853b1da64f4d
user: jgoecks
date: 2013-01-27 21:19:27
summary: Cleanup and documentation for method that gets genome's chromosome information.
affected #: 1 file
diff -r f36d5d615dd4775d71ee778f500bd0c1d3fdf68e -r 853b1da64f4db37e93d1cbf43b6d0b5f45e63d38 lib/galaxy/visualization/genomes.py
--- a/lib/galaxy/visualization/genomes.py
+++ b/lib/galaxy/visualization/genomes.py
@@ -215,8 +215,7 @@
dbkeys.extend( [ ( genome.description, genome.key ) for key, genome in self.genomes.items() if filter_fn( genome ) ] )
return dbkeys
- #return [ (v, k) for k, v in trans.db_builds if ( ( k in self.genomes and self.genomes[ k ].len_file ) or k in user_keys ) ]
-
+
def chroms( self, trans, dbkey=None, num=None, chrom=None, low=None ):
"""
@@ -256,15 +255,25 @@
genome = Genome( dbkey, dbkey_name, len_file=len_file, twobit_file=twobit_file )
- # Look in system builds.
+ # Look in history and system builds.
if not genome:
+ # Look in history for chromosome len file.
len_ds = trans.db_dataset_for( dbkey )
- if not len_ds:
+ if len_ds:
+ genome = Genome( dbkey, dbkey_name, len_file=len_ds.file_name )
+ # Look in system builds.
+ elif dbkey in self.genomes:
genome = self.genomes[ dbkey ]
- else:
- genome = Genome( dbkey, dbkey_name, len_file=len_ds.file_name )
+
+ # Set up return value or log exception if genome not found for key.
+ rval = None
+ if genome:
+ rval = genome.to_dict( num=num, chrom=chrom, low=low )
+ else:
+ log.exception( 'genome not found for key %s' % dbkey )
- return genome.to_dict( num=num, chrom=chrom, low=low )
+ return rval
+
def has_reference_data( self, trans, dbkey, dbkey_owner=None ):
"""
https://bitbucket.org/galaxy/galaxy-central/commits/18d528947af2/
changeset: 18d528947af2
user: jgoecks
date: 2013-01-28 00:13:13
summary: Reinstate grid footer updates because they now work again with embedded grids. This also prevents spurious grid posts.
affected #: 1 file
diff -r 853b1da64f4db37e93d1cbf43b6d0b5f45e63d38 -r 18d528947af20aca02f105722a844d32f90fa0ec templates/grid_base.mako
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -569,7 +569,7 @@
$('#grid-table-body').html(parsed_response_text[0]);
// FIXME: this does not work at all; what's needed is a function
// that updates page links when number of pages changes.
- //$('#grid-table-footer').html(parsed_response_text[1]);
+ $('#grid-table-footer').html(parsed_response_text[1]);
// Trigger custom event to indicate grid body has changed.
$('#grid-table-body').trigger('update');
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0