Conflicts:
	static/scripts/packed/mvc/tools/tools-form-base.js
This commit is contained in:
guerler
2015-02-28 05:15:02 -05:00
22 changed files with 468 additions and 261 deletions
+14 -1
View File
@@ -38,7 +38,7 @@ Not all dependencies are included for the tools provided in the sample
https://wiki.galaxyproject.org/Admin/Tools/ToolDependencies
Issues
------
======
Issues can be submitted to trello via the `galaxyproject
website <http://galaxyproject.org/trello/>`__ and viewed on the `Galaxy
@@ -51,6 +51,19 @@ Galaxy Development
Galaxy welcomes new development! There is extensive documentation on developing
with Galaxy on the `wiki <https://wiki.galaxyproject.org/Develop>`__.
Source Repository
-----------------
Galaxy development has moved to `Github
<https://github.com/galaxyproject/galaxy>`__.
**Developers** should develop against the ``dev`` branch in the Github
repository.
**Deployers** can continue to pull Galaxy changes from Bitbucket without
interruption. Alternatively, deployers can track the ``master`` branch in
Github.
Syncing a Fork
--------------
@@ -108,7 +108,7 @@ define(['utils/utils', 'utils/deferred', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc',
var new_state = self.tree.finalize();
if (!_.isEqual(new_state, current_state)) {
current_state = new_state;
self._updateModel($.extend({}, current_state));
self._updateModel($.extend(true, {}, current_state));
}
});
});
@@ -1,3 +1,3 @@
<input type="text" name="query" value="{{search_hint_string}}" id="tool-search-query" autocomplete="off" class="search-query parent-width" />
<input type="text" name="query" placeholder="{{search_hint_string}}" id="tool-search-query" autocomplete="off" class="search-query parent-width" />
<a id="search-clear-btn" title="clear search (esc)"> </a>
<img src="{{spinner_url}}" id="search-spinner" class="search-spinner"/>
<img src="{{spinner_url}}" id="search-spinner" class="search-spinner"/>
+1 -1
View File
@@ -180,7 +180,7 @@
<datatype extension="scf" type="galaxy.datatypes.binary:Scf" mimetype="application/octet-stream" display_in_upload="true" description="A binary sequence file in 'scf' format with a '.scf' file extension. You must manually select this 'File Format' when uploading the file." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Scf"/>
<datatype extension="Sequences" type="galaxy.datatypes.assembly:Sequences" display_in_upload="false"/>
<datatype extension="snpeffdb" type="galaxy.datatypes.text:SnpEffDb" display_in_upload="True"/>
<datatype extension="snpsiftdbnsfp" type="galaxy.datatypes.txt:SnpSiftDbNSFP" display_in_upload="True"/>
<datatype extension="snpsiftdbnsfp" type="galaxy.datatypes.text:SnpSiftDbNSFP" display_in_upload="True"/>
<datatype extension="dbnsfp.tabular" type="galaxy.datatypes.tabular:Tabular" subclass="True" display_in_upload="True">
<converter file="tabular_to_dbnsfp.xml" target_datatype="snpsiftdbnsfp"/>
</datatype>
+5
View File
@@ -65,4 +65,9 @@
<columns>value, path</columns>
<file path="tool-data/twobit.loc" />
</table>
<!-- Available IGV builds, loaded from URL -->
<table name="igv_broad_genomes" comment_char="#">
<columns>name, url, value</columns>
<file url="http://igv.broadinstitute.org/genomes/genomes.txt" />
</table>
</tables>
+14 -1
View File
@@ -93,7 +93,20 @@
#end if
</param>
</dynamic_links>
<dynamic_links from_data_table="igv_broad_genomes" skip_startswith="#" id="value" name="name">
<!-- Our input data table is one line per dbkey -->
<filter>${ $dataset.dbkey == $value }</filter>
<!-- We define url and params as normal, but values defined in dynamic_param are available by specified name -->
<url>http://www.broadinstitute.org/igv/projects/current/igv.php?sessionURL=${bam_file.qp}&amp;genome=${bam_file.dbkey}&amp;merge=true&amp;name=${qp( $bam_file.name )}</url>
<param type="data" name="bam_file" url="galaxy_${DATASET_HASH}.bam" />
<param type="data" name="bai_file" url="galaxy_${DATASET_HASH}.bam.bai" metadata="bam_index" />
</dynamic_links>
</display>
<!-- Dan Blankenberg -->
+14 -1
View File
@@ -93,7 +93,20 @@
#end if
</param>
</dynamic_links>
<dynamic_links from_data_table="igv_broad_genomes" skip_startswith="#" id="value" name="name">
<!-- Our input data table is one line per dbkey -->
<filter>${ $dataset.dbkey == $value }</filter>
<!-- We define url and params as normal, but values defined in dynamic_param are available by specified name -->
<url>http://www.broadinstitute.org/igv/projects/current/igv.php?sessionURL=${bgzip_file.qp}&amp;genome=$bgzip_file.dbkey&amp;merge=true&amp;name=${qp( $bgzip_file.name )}</url>
<param type="data" name="bgzip_file" url="galaxy_${DATASET_HASH}.vcf.gz" format="vcf_bgzip" />
<param type="data" name="tabix_file" dataset="bgzip_file" url="galaxy_${DATASET_HASH}.vcf.gz.tbi" format="tabix" />
</dynamic_links>
</display>
<!-- Dan Blankenberg -->
+1 -1
View File
@@ -88,7 +88,7 @@ class UniverseApplication( object, config.ConfiguresGalaxyMixin ):
# Load proprietary datatype converters and display applications.
self.installed_repository_manager.load_proprietary_converters_and_display_applications()
# Load datatype display applications defined in local datatypes_conf.xml
self.datatypes_registry.load_display_applications()
self.datatypes_registry.load_display_applications( self )
# Load datatype converters defined in local datatypes_conf.xml
self.datatypes_registry.load_datatype_converters( self.toolbox )
# Load external metadata tool
@@ -80,21 +80,57 @@ class DisplayApplicationLink( object ):
return True
class DynamicDisplayApplicationBuilder( object ):
@classmethod
def __init__( self, elem, display_application, build_sites ):
rval = []
filename = None
data_table = None
if elem.get( 'site_type', None ) is not None:
filename = build_sites.get( elem.get( 'site_type' ) )
else:
filename = elem.get( 'from_file', None )
assert filename is not None, 'Filename and id attributes required for dynamic_links'
if filename is None:
data_table_name = elem.get( 'from_data_table', None )
if data_table_name:
data_table = display_application.app.tool_data_tables.get( data_table_name, None )
assert data_table is not None, 'Unable to find data table named "%s".' % data_table_name
assert filename is not None or data_table is not None,'Filename or data Table is required for dynamic_links.'
skip_startswith = elem.get( 'skip_startswith', None )
separator = elem.get( 'separator', '\t' )
id_col = int( elem.get( 'id', None ) )
name_col = int( elem.get( 'name', id_col ) )
dynamic_params = {}
id_col = elem.get( 'id', None )
try:
id_col = int( id_col )
except:
if data_table:
if id_col is None:
id_col = data_table.columns.get( 'id', None )
if id_col is None:
id_col = data_table.columns.get( 'value', None )
try:
id_col = int( id_col )
except:
# id is set to a string or None, use column by that name if available
id_col = data_table.columns.get( id_col, None )
id_col = int( id_col )
name_col = elem.get( 'name', None )
try:
name_col = int( name_col )
except:
if data_table:
if name_col is None:
name_col = data_table.columns.get( 'name', None )
else:
name_col = data_table.columns.get( name_col, None )
else:
name_col = None
if name_col is None:
name_col = id_col
max_col = max( id_col, name_col )
dynamic_params = {}
if data_table is not None:
max_col = max( [ max_col ] + data_table.columns.values() )
for key, value in data_table.columns.items():
dynamic_params[key] = { 'column': value, 'split': False, 'separator': ',' }
for dynamic_param in elem.findall( 'dynamic_param' ):
name = dynamic_param.get( 'name' )
value = int( dynamic_param.get( 'value' ) )
@@ -102,27 +138,38 @@ class DynamicDisplayApplicationBuilder( object ):
param_separator = dynamic_param.get( 'separator', ',' )
max_col = max( max_col, value )
dynamic_params[name] = { 'column': value, 'split': split, 'separator': param_separator }
for line in open( filename ):
if not skip_startswith or not line.startswith( skip_startswith ):
line = line.rstrip( '\n\r' )
if not line:
continue
fields = line.split( separator )
if len( fields ) > max_col:
new_elem = deepcopy( elem )
new_elem.set( 'id', fields[id_col] )
new_elem.set( 'name', fields[name_col] )
dynamic_values = {}
for key, attributes in dynamic_params.iteritems():
value = fields[ attributes[ 'column' ] ]
if attributes['split']:
value = value.split( attributes['separator'] )
dynamic_values[key] = value
#now populate
rval.append( DisplayApplicationLink.from_elem( new_elem, display_application, other_values = dynamic_values ) )
if filename:
data_iter = open( filename )
elif data_table:
version, data_iter = data_table.get_version_fields()
display_application.add_data_table_watch( data_table.name, version )
links = []
for line in data_iter:
if isinstance( line, basestring ):
if not skip_startswith or not line.startswith( skip_startswith ):
line = line.rstrip( '\n\r' )
if not line:
continue
fields = line.split( separator )
else:
log.warning( 'Invalid dynamic display application link specified in %s: "%s"' % ( filename, line ) )
self.links = rval
continue
else:
fields = line
if len( fields ) > max_col:
new_elem = deepcopy( elem )
new_elem.set( 'id', fields[id_col] )
new_elem.set( 'name', fields[name_col] )
dynamic_values = {}
for key, attributes in dynamic_params.iteritems():
value = fields[ attributes[ 'column' ] ]
if attributes['split']:
value = value.split( attributes['separator'] )
dynamic_values[key] = value
#now populate
links.append( DisplayApplicationLink.from_elem( new_elem, display_application, other_values = dynamic_values ) )
else:
log.warning( 'Invalid dynamic display application link specified in %s: "%s"' % ( filename, line ) )
self.links = links
def __iter__( self ):
return iter( self.links )
@@ -166,12 +213,12 @@ class PopulatedDisplayApplicationLink( object ):
class DisplayApplication( object ):
@classmethod
def from_file( cls, filename, datatypes_registry ):
return cls.from_elem( parse_xml( filename ).getroot(), datatypes_registry, filename=filename )
def from_file( cls, filename, app ):
return cls.from_elem( parse_xml( filename ).getroot(), app, filename=filename )
@classmethod
def from_elem( cls, elem, datatypes_registry, filename=None ):
def from_elem( cls, elem, app, filename=None ):
att_dict = cls._get_attributes_from_elem( elem )
rval = DisplayApplication( att_dict['id'], att_dict['name'], datatypes_registry, att_dict['version'], filename=filename, elem=elem )
rval = DisplayApplication( att_dict['id'], att_dict['name'], app, att_dict['version'], filename=filename, elem=elem )
rval._load_links_from_elem( elem )
return rval
@classmethod
@@ -181,29 +228,32 @@ class DisplayApplication( object ):
name = elem.get( 'name', display_id )
version = elem.get( 'version', None )
return dict( id=display_id, name=name, version=version )
def __init__( self, display_id, name, datatypes_registry, version = None, filename=None, elem=None ):
def __init__( self, display_id, name, app, version = None, filename=None, elem=None ):
self.id = display_id
self.name = name
self.datatypes_registry = datatypes_registry
self.app = app
if version is None:
version = "1.0.0"
self.version = version
self.links = odict()
self._filename = filename
self._elem = elem
self._data_table_versions = {}
def _load_links_from_elem( self, elem ):
for link_elem in elem.findall( 'link' ):
link = DisplayApplicationLink.from_elem( link_elem, self )
if link:
self.links[ link.id ] = link
for dynamic_links in elem.findall( 'dynamic_links' ):
for link in DynamicDisplayApplicationBuilder( dynamic_links, self, self.datatypes_registry.build_sites ):
for link in DynamicDisplayApplicationBuilder( dynamic_links, self, self.app.datatypes_registry.build_sites ):
self.links[ link.id ] = link
def get_link( self, link_name, data, dataset_hash, user_hash, trans, app_kwds ):
#returns a link object with data knowledge to generate links
self._check_and_reload()
return PopulatedDisplayApplicationLink( self.links[ link_name ], data, dataset_hash, user_hash, trans, app_kwds )
def filter_by_dataset( self, data, trans ):
filtered = DisplayApplication( self.id, self.name, self.datatypes_registry, version = self.version )
self._check_and_reload()
filtered = DisplayApplication( self.id, self.name, self.app, version = self.version )
for link_name, link_value in self.links.iteritems():
if link_value.filter_by_dataset( data, trans ):
filtered.links[link_name] = link_value
@@ -222,9 +272,24 @@ class DisplayApplication( object ):
# clear old links
for key in self.links.keys():
del self.links[key]
#clear data table versions:
for key in self._data_table_versions.keys():
del self._data_table_versions[ key ]
# Set new attributes
for key, value in attr_dict.iteritems():
setattr( self, key, value )
# Load new links
self._load_links_from_elem( elem )
return self
def add_data_table_watch( self, table_name, version=None ):
self._data_table_versions[ table_name ] = version
def _requires_reload( self ):
for key, value in self._data_table_versions.iteritems():
table = self.app.tool_data_tables.get( key, None )
if table and not table.is_current_version( value ):
return True
return False
def _check_and_reload( self ):
if self._requires_reload():
self.reload()
@@ -59,7 +59,7 @@ class DisplayApplicationDataParameter( DisplayApplicationParameter ):
@property
def formats( self ):
if self.extensions:
return tuple( map( type, map( self.link.display_application.datatypes_registry.get_datatype_by_extension, self.extensions ) ) )
return tuple( map( type, map( self.link.display_application.app.datatypes_registry.get_datatype_by_extension, self.extensions ) ) )
return None
def _get_dataset_like_object( self, other_values ):
#this returned object has file_name, state, and states attributes equivalent to a DatasetAssociation
+2 -2
View File
@@ -546,7 +546,7 @@ class Registry( object ):
else:
self.log.exception( "Error loading converter (%s): %s" % ( converter_path, str( e ) ) )
def load_display_applications( self, installed_repository_dict=None, deactivate=False ):
def load_display_applications( self, app, installed_repository_dict=None, deactivate=False ):
"""
If deactivate is False, add display applications from self.display_app_containers or
self.proprietary_display_app_containers to appropriate datatypes. If deactivate is
@@ -570,7 +570,7 @@ class Registry( object ):
config_path = os.path.join( self.display_applications_path, display_file )
try:
inherit = galaxy.util.string_as_bool( display_app.get( 'inherit', 'False' ) )
display_app = DisplayApplication.from_file( config_path, self )
display_app = DisplayApplication.from_file( config_path, app )
if display_app:
if display_app.id in self.display_applications:
if deactivate:
+88
View File
@@ -203,6 +203,94 @@ class Sequence( data.Text ):
return None
raise NotImplementedError("Can't split generic sequence files")
def get_split_commands_with_toc(input_name, output_name, toc_file, start_sequence, sequence_count):
"""
Uses a Table of Contents dict, parsed from an FQTOC file, to come up with a set of
shell commands that will extract the parts necessary
>>> three_sections=[dict(start=0, end=74, sequences=10), dict(start=74, end=148, sequences=10), dict(start=148, end=148+76, sequences=10)]
>>> Sequence.get_split_commands_with_toc('./input.gz', './output.gz', dict(sections=three_sections), start_sequence=0, sequence_count=10)
['dd bs=1 skip=0 count=74 if=./input.gz 2> /dev/null >> ./output.gz']
>>> Sequence.get_split_commands_with_toc('./input.gz', './output.gz', dict(sections=three_sections), start_sequence=1, sequence_count=5)
['(dd bs=1 skip=0 count=74 if=./input.gz 2> /dev/null )| zcat | ( tail -n +5 2> /dev/null) | head -20 | gzip -c >> ./output.gz']
>>> Sequence.get_split_commands_with_toc('./input.gz', './output.gz', dict(sections=three_sections), start_sequence=0, sequence_count=20)
['dd bs=1 skip=0 count=148 if=./input.gz 2> /dev/null >> ./output.gz']
>>> Sequence.get_split_commands_with_toc('./input.gz', './output.gz', dict(sections=three_sections), start_sequence=5, sequence_count=10)
['(dd bs=1 skip=0 count=74 if=./input.gz 2> /dev/null )| zcat | ( tail -n +21 2> /dev/null) | head -20 | gzip -c >> ./output.gz', '(dd bs=1 skip=74 count=74 if=./input.gz 2> /dev/null )| zcat | ( tail -n +1 2> /dev/null) | head -20 | gzip -c >> ./output.gz']
>>> Sequence.get_split_commands_with_toc('./input.gz', './output.gz', dict(sections=three_sections), start_sequence=10, sequence_count=10)
['dd bs=1 skip=74 count=74 if=./input.gz 2> /dev/null >> ./output.gz']
>>> Sequence.get_split_commands_with_toc('./input.gz', './output.gz', dict(sections=three_sections), start_sequence=5, sequence_count=20)
['(dd bs=1 skip=0 count=74 if=./input.gz 2> /dev/null )| zcat | ( tail -n +21 2> /dev/null) | head -20 | gzip -c >> ./output.gz', 'dd bs=1 skip=74 count=74 if=./input.gz 2> /dev/null >> ./output.gz', '(dd bs=1 skip=148 count=76 if=./input.gz 2> /dev/null )| zcat | ( tail -n +1 2> /dev/null) | head -20 | gzip -c >> ./output.gz']
"""
sections = toc_file['sections']
result = []
current_sequence = long(0)
i=0
# skip to the section that contains my starting sequence
while i < len(sections) and start_sequence >= current_sequence + long(sections[i]['sequences']):
current_sequence += long(sections[i]['sequences'])
i += 1
if i == len(sections): # bad input data!
raise Exception('No FQTOC section contains starting sequence %s' % start_sequence)
# These two variables act as an accumulator for consecutive entire blocks that
# can be copied verbatim (without decompressing)
start_chunk = long(-1)
end_chunk = long(-1)
copy_chunk_cmd = 'dd bs=1 skip=%s count=%s if=%s 2> /dev/null >> %s'
while sequence_count > 0 and i < len(sections):
# we need to extract partial data. So, find the byte offsets of the chunks that contain the data we need
# use a combination of dd (to pull just the right sections out) tail (to skip lines) and head (to get the
# right number of lines
sequences = long(sections[i]['sequences'])
skip_sequences = start_sequence-current_sequence
sequences_to_extract = min(sequence_count, sequences-skip_sequences)
start_copy = long(sections[i]['start'])
end_copy = long(sections[i]['end'])
if sequences_to_extract < sequences:
if start_chunk > -1:
result.append(copy_chunk_cmd % (start_chunk, end_chunk-start_chunk, input_name, output_name))
start_chunk = -1
# extract, unzip, trim, recompress
result.append('(dd bs=1 skip=%s count=%s if=%s 2> /dev/null )| zcat | ( tail -n +%s 2> /dev/null) | head -%s | gzip -c >> %s' %
(start_copy, end_copy-start_copy, input_name, skip_sequences*4+1, sequences_to_extract*4, output_name))
else: # whole section - add it to the start_chunk/end_chunk accumulator
if start_chunk == -1:
start_chunk = start_copy
end_chunk = end_copy
sequence_count -= sequences_to_extract
start_sequence += sequences_to_extract
current_sequence += sequences
i += 1
if start_chunk > -1:
result.append(copy_chunk_cmd % (start_chunk, end_chunk-start_chunk, input_name, output_name))
if sequence_count > 0:
raise Exception('%s sequences not found in file' % sequence_count)
return result
get_split_commands_with_toc = staticmethod(get_split_commands_with_toc)
def get_split_commands_sequential(is_compressed, input_name, output_name, start_sequence, sequence_count):
"""
Does a brain-dead sequential scan & extract of certain sequences
>>> Sequence.get_split_commands_sequential(True, './input.gz', './output.gz', start_sequence=0, sequence_count=10)
['zcat "./input.gz" | ( tail -n +1 2> /dev/null) | head -40 | gzip -c > "./output.gz"']
>>> Sequence.get_split_commands_sequential(False, './input.fastq', './output.fastq', start_sequence=10, sequence_count=10)
['tail -n +41 "./input.fastq" 2> /dev/null | head -40 > "./output.fastq"']
"""
start_line = start_sequence * 4
line_count = sequence_count * 4
# TODO: verify that tail can handle 64-bit numbers
if is_compressed:
cmd = 'zcat "%s" | ( tail -n +%s 2> /dev/null) | head -%s | gzip -c' % (input_name, start_line+1, line_count)
else:
cmd = 'tail -n +%s "%s" 2> /dev/null | head -%s' % (start_line+1, input_name, line_count)
cmd += ' > "%s"' % output_name
return [cmd]
get_split_commands_sequential = staticmethod(get_split_commands_sequential)
class Alignment( data.Text ):
"""Class describing an alignment"""
+17 -97
View File
@@ -1,6 +1,5 @@
import os
import re
import shutil
import string
import tarfile
import tempfile
@@ -23,6 +22,7 @@ from .panel import ToolPanelElements
from .panel import ToolSectionLabel
from .panel import ToolSection
from .panel import panel_item_types
from .integrated_panel import ManagesIntegratedToolPanelMixin
from .lineages import LineageMap
from .tags import tool_tag_manager
@@ -37,22 +37,7 @@ import logging
log = logging.getLogger( __name__ )
INTEGRATED_TOOL_PANEL_DESCRIPTION = """
This is Galaxy's integrated tool panel and should be modified directly only for
reordering tools inside a section. Each time Galaxy starts up, this file is
synchronized with the various tool config files: tools, sections and labels
added to one of these files, will be added also here in the appropriate place,
while elements removed from the tool config files will be correspondingly
deleted from this file.
To modify locally managed tools (e.g. from tool_conf.xml) modify that file
directly and restart Galaxy. Whenever possible Tool Shed managed tools (e.g.
from shed_tool_conf.xml) should be managed from within the Galaxy interface or
via its API - but if changes are necessary (such as to hide a tool or re-assign
its section) modify that file and restart Galaxy.
"""
class AbstractToolBox( object, Dictifiable ):
class AbstractToolBox( object, Dictifiable, ManagesIntegratedToolPanelMixin ):
"""
Abstract container for managing a ToolPanel - containing tools and
workflows optionally in labelled sections.
@@ -78,15 +63,8 @@ class AbstractToolBox( object, Dictifiable ):
self._index = 0
self.data_manager_tools = odict()
self._lineage_map = LineageMap( app )
# File that contains the XML section and tool tags from all tool panel config files integrated into a
# single file that defines the tool panel layout. This file can be changed by the Galaxy administrator
# (in a way similar to the single tool_conf.xml file in the past) to alter the layout of the tool panel.
self._integrated_tool_panel_config = app.config.integrated_tool_panel_config
# In-memory dictionary that defines the layout of the tool_panel.xml file on disk.
self._integrated_tool_panel = ToolPanelElements()
self._integrated_tool_panel_config_has_contents = os.path.exists( self._integrated_tool_panel_config ) and os.stat( self._integrated_tool_panel_config ).st_size > 0
if self._integrated_tool_panel_config_has_contents:
self._load_integrated_tool_panel_keys()
# Sets self._integrated_tool_panel and self._integrated_tool_panel_config_has_contents
self._init_integrated_tool_panel( app.config )
# The following refers to the tool_path config setting for backward compatibility. The shed-related
# (e.g., shed_tool_conf.xml) files include the tool_path attribute within the <toolbox> tag.
self._tool_root_dir = tool_root_dir
@@ -98,12 +76,7 @@ class AbstractToolBox( object, Dictifiable ):
if self.app.name == 'galaxy' and self._integrated_tool_panel_config_has_contents:
# Load self._tool_panel based on the order in self._integrated_tool_panel.
self._load_tool_panel()
if app.config.update_integrated_tool_panel:
# Write the current in-memory integrated_tool_panel to the integrated_tool_panel.xml file.
# This will cover cases where the Galaxy administrator manually edited one or more of the tool panel
# config files, adding or removing locally developed tools or workflows. The value of integrated_tool_panel
# will be False when things like functional tests are the caller.
self._write_integrated_tool_panel_config_file()
self._save_integrated_tool_panel()
def create_tool( self, config_file, repository_id=None, guid=None, **kwds ):
raise NotImplementedError()
@@ -215,9 +188,8 @@ class AbstractToolBox( object, Dictifiable ):
for index, my_shed_tool_conf in enumerate( self._dynamic_tool_confs ):
if shed_conf['config_filename'] == my_shed_tool_conf['config_filename']:
self._dynamic_tool_confs[ index ] = shed_conf
if integrated_panel_changes and app.config.update_integrated_tool_panel:
# Write the current in-memory version of the integrated_tool_panel.xml file to disk.
self._write_integrated_tool_panel_config_file()
if integrated_panel_changes:
self._save_integrated_tool_panel()
app.reindex_tool_search()
def get_section( self, section_id, new_label=None, create_if_needed=False ):
@@ -237,7 +209,7 @@ class AbstractToolBox( object, Dictifiable ):
'version': '',
}
tool_section = ToolSection( section_dict )
self._tool_panel[ tool_panel_section_key ] = tool_section
self._tool_panel.append_section( tool_panel_section_key, tool_section )
log.debug( "Loading new tool panel section: %s" % str( tool_section.name ) )
else:
tool_section = None
@@ -400,52 +372,6 @@ class AbstractToolBox( object, Dictifiable ):
elif elem.tag == 'label':
self._integrated_tool_panel.stub_label( key )
def _write_integrated_tool_panel_config_file( self ):
"""
Write the current in-memory version of the integrated_tool_panel.xml file to disk. Since Galaxy administrators
use this file to manage the tool panel, we'll not use xml_to_string() since it doesn't write XML quite right.
"""
fd, filename = tempfile.mkstemp()
os.write( fd, '<?xml version="1.0"?>\n' )
os.write( fd, '<toolbox>\n' )
os.write( fd, ' <!--\n ')
os.write( fd, '\n '.join( [ l for l in INTEGRATED_TOOL_PANEL_DESCRIPTION.split("\n") if l ] ) )
os.write( fd, '\n -->\n')
for key, item_type, item in self._integrated_tool_panel.panel_items_iter():
if item:
if item_type == panel_item_types.TOOL:
os.write( fd, ' <tool id="%s" />\n' % item.id )
elif item_type == panel_item_types.WORKFLOW:
os.write( fd, ' <workflow id="%s" />\n' % item.id )
elif item_type == panel_item_types.LABEL:
label_id = item.id or ''
label_text = item.text or ''
label_version = item.version or ''
os.write( fd, ' <label id="%s" text="%s" version="%s" />\n' % ( label_id, label_text, label_version ) )
elif item_type == panel_item_types.SECTION:
section_id = item.id or ''
section_name = item.name or ''
section_version = item.version or ''
os.write( fd, ' <section id="%s" name="%s" version="%s">\n' % ( section_id, section_name, section_version ) )
for section_key, section_item_type, section_item in item.panel_items_iter():
if section_item_type == panel_item_types.TOOL:
if section_item:
os.write( fd, ' <tool id="%s" />\n' % section_item.id )
elif section_item_type == panel_item_types.WORKFLOW:
if section_item:
os.write( fd, ' <workflow id="%s" />\n' % section_item.id )
elif section_item_type == panel_item_types.LABEL:
if section_item:
label_id = section_item.id or ''
label_text = section_item.text or ''
label_version = section_item.version or ''
os.write( fd, ' <label id="%s" text="%s" version="%s" />\n' % ( label_id, label_text, label_version ) )
os.write( fd, ' </section>\n' )
os.write( fd, '</toolbox>\n' )
os.close( fd )
shutil.move( filename, os.path.abspath( self._integrated_tool_panel_config ) )
os.chmod( self._integrated_tool_panel_config, 0644 )
def get_tool( self, tool_id, tool_version=None, get_all_versions=False, exact=False ):
"""Attempt to locate a tool in the tool box."""
if tool_version:
@@ -457,9 +383,9 @@ class AbstractToolBox( object, Dictifiable ):
if tool_id in self._tools_by_id and not get_all_versions:
if tool_version and tool_version in self._tool_versions_by_id[ tool_id ]:
return self._tool_versions_by_id[ tool_id ][ tool_version ]
#tool_id exactly matches an available tool by id (which is 'old' tool_id or guid)
# tool_id exactly matches an available tool by id (which is 'old' tool_id or guid)
return self._tools_by_id[ tool_id ]
#exact tool id match not found, or all versions requested, search for other options, e.g. migrated tools or different versions
# exact tool id match not found, or all versions requested, search for other options, e.g. migrated tools or different versions
rval = []
tool_lineage = self._lineage_map.get( tool_id )
if tool_lineage:
@@ -469,7 +395,7 @@ class AbstractToolBox( object, Dictifiable ):
if lineage_tool:
rval.append( lineage_tool )
if not rval:
#still no tool, do a deeper search and try to match by old ids
# still no tool, do a deeper search and try to match by old ids
for tool in self._tools_by_id.itervalues():
if tool.old_id == tool_id:
rval.append( tool )
@@ -478,14 +404,14 @@ class AbstractToolBox( object, Dictifiable ):
return rval
else:
if tool_version:
#return first tool with matching version
# return first tool with matching version
for tool in rval:
if tool.version == tool_version:
return tool
#No tool matches by version, simply return the first available tool found
# No tool matches by version, simply return the first available tool found
return rval[0]
#We now likely have a Toolshed guid passed in, but no supporting database entries
#If the tool exists by exact id and is loaded then provide exact match within a list
# We now likely have a Toolshed guid passed in, but no supporting database entries
# If the tool exists by exact id and is loaded then provide exact match within a list
if tool_id in self._tools_by_id:
return[ self._tools_by_id[ tool_id ] ]
return None
@@ -777,13 +703,7 @@ class AbstractToolBox( object, Dictifiable ):
if async:
self._load_tool_panel()
if self.app.config.update_integrated_tool_panel:
# Write the current in-memory integrated_tool_panel to the integrated_tool_panel.xml file.
# This will cover cases where the Galaxy administrator manually edited one or more of the tool panel
# config files, adding or removing locally developed tools or workflows. The value of integrated_tool_panel
# will be False when things like functional tests are the caller.
self._write_integrated_tool_panel_config_file()
self._save_integrated_tool_panel()
return tool.id
except Exception:
log.exception("Failed to load potential tool %s." % tool_file)
@@ -1012,7 +932,7 @@ class AbstractToolBox( object, Dictifiable ):
break
if tool_id in self.data_manager_tools:
del self.data_manager_tools[ tool_id ]
#TODO: do we need to manually remove from the integrated panel here?
# TODO: do we need to manually remove from the integrated panel here?
message = "Removed the tool:<br/>"
message += "<b>name:</b> %s<br/>" % tool.name
message += "<b>id:</b> %s<br/>" % tool.id
@@ -0,0 +1,87 @@
import os
import shutil
import tempfile
from .panel import ToolPanelElements
from .panel import panel_item_types
INTEGRATED_TOOL_PANEL_DESCRIPTION = """
This is Galaxy's integrated tool panel and should be modified directly only for
reordering tools inside a section. Each time Galaxy starts up, this file is
synchronized with the various tool config files: tools, sections and labels
added to one of these files, will be added also here in the appropriate place,
while elements removed from the tool config files will be correspondingly
deleted from this file.
To modify locally managed tools (e.g. from tool_conf.xml) modify that file
directly and restart Galaxy. Whenever possible Tool Shed managed tools (e.g.
from shed_tool_conf.xml) should be managed from within the Galaxy interface or
via its API - but if changes are necessary (such as to hide a tool or re-assign
its section) modify that file and restart Galaxy.
"""
class ManagesIntegratedToolPanelMixin:
def _init_integrated_tool_panel(self, config):
self.update_integrated_tool_panel = config.update_integrated_tool_panel
self._integrated_tool_panel_config = config.integrated_tool_panel_config
# In-memory dictionary that defines the layout of the tool_panel.xml file on disk.
self._integrated_tool_panel = ToolPanelElements()
self._integrated_tool_panel_config_has_contents = os.path.exists( self._integrated_tool_panel_config ) and os.stat( self._integrated_tool_panel_config ).st_size > 0
if self._integrated_tool_panel_config_has_contents:
self._load_integrated_tool_panel_keys()
def _save_integrated_tool_panel(self):
if self.update_integrated_tool_panel:
# Write the current in-memory integrated_tool_panel to the integrated_tool_panel.xml file.
# This will cover cases where the Galaxy administrator manually edited one or more of the tool panel
# config files, adding or removing locally developed tools or workflows. The value of integrated_tool_panel
# will be False when things like functional tests are the caller.
self._write_integrated_tool_panel_config_file()
def _write_integrated_tool_panel_config_file( self ):
"""
Write the current in-memory version of the integrated_tool_panel.xml file to disk. Since Galaxy administrators
use this file to manage the tool panel, we'll not use xml_to_string() since it doesn't write XML quite right.
"""
fd, filename = tempfile.mkstemp()
os.write( fd, '<?xml version="1.0"?>\n' )
os.write( fd, '<toolbox>\n' )
os.write( fd, ' <!--\n ')
os.write( fd, '\n '.join( [ l for l in INTEGRATED_TOOL_PANEL_DESCRIPTION.split("\n") if l ] ) )
os.write( fd, '\n -->\n')
for key, item_type, item in self._integrated_tool_panel.panel_items_iter():
if item:
if item_type == panel_item_types.TOOL:
os.write( fd, ' <tool id="%s" />\n' % item.id )
elif item_type == panel_item_types.WORKFLOW:
os.write( fd, ' <workflow id="%s" />\n' % item.id )
elif item_type == panel_item_types.LABEL:
label_id = item.id or ''
label_text = item.text or ''
label_version = item.version or ''
os.write( fd, ' <label id="%s" text="%s" version="%s" />\n' % ( label_id, label_text, label_version ) )
elif item_type == panel_item_types.SECTION:
section_id = item.id or ''
section_name = item.name or ''
section_version = item.version or ''
os.write( fd, ' <section id="%s" name="%s" version="%s">\n' % ( section_id, section_name, section_version ) )
for section_key, section_item_type, section_item in item.panel_items_iter():
if section_item_type == panel_item_types.TOOL:
if section_item:
os.write( fd, ' <tool id="%s" />\n' % section_item.id )
elif section_item_type == panel_item_types.WORKFLOW:
if section_item:
os.write( fd, ' <workflow id="%s" />\n' % section_item.id )
elif section_item_type == panel_item_types.LABEL:
if section_item:
label_id = section_item.id or ''
label_text = section_item.text or ''
label_version = section_item.version or ''
os.write( fd, ' <label id="%s" text="%s" version="%s" />\n' % ( label_id, label_text, label_version ) )
os.write( fd, ' </section>\n' )
os.write( fd, '</toolbox>\n' )
os.close( fd )
shutil.move( filename, os.path.abspath( self._integrated_tool_panel_config ) )
os.chmod( self._integrated_tool_panel_config, 0644 )
@@ -637,32 +637,6 @@ class AdminToolshed( AdminGalaxy ):
message=message,
status=status )
@web.expose
@web.require_admin
def install_tool_shed_repositories( self, trans, tool_shed_repositories, reinstalling=False, **kwd ):
"""Install specified tool shed repositories."""
shed_tool_conf = kwd.get( 'shed_tool_conf', '' )
tool_path = kwd[ 'tool_path' ]
install_tool_dependencies = CheckboxField.is_checked( kwd.get( 'install_tool_dependencies', '' ) )
# There must be a one-to-one mapping between items in the 3 lists: tool_shed_repositories, tool_panel_section_keys, repo_info_dicts.
tool_panel_section_keys = util.listify( kwd[ 'tool_panel_section_keys' ] )
repo_info_dicts = util.listify( kwd[ 'repo_info_dicts' ] )
irm = install_manager.InstallRepositoryManager( trans.app )
for index, tool_shed_repository in enumerate( tool_shed_repositories ):
repo_info_dict = repo_info_dicts[ index ]
tool_panel_section_key = tool_panel_section_keys[ index ]
irm.install_tool_shed_repository( tool_shed_repository,
repo_info_dict,
tool_panel_section_key,
shed_tool_conf,
tool_path,
install_tool_dependencies,
reinstalling=reinstalling )
tsr_ids_for_monitoring = [ trans.security.encode_id( tsr.id ) for tsr in tool_shed_repositories ]
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
action='monitor_repository_installation',
tool_shed_repository_ids=tsr_ids_for_monitoring ) )
@web.expose
@web.require_admin
def manage_repositories( self, trans, **kwd ):
@@ -704,41 +678,21 @@ class AdminToolshed( AdminGalaxy ):
reinstalling = util.string_as_bool( kwd.get( 'reinstalling', False ) )
encoded_kwd = kwd[ 'encoded_kwd' ]
decoded_kwd = encoding_util.tool_shed_decode( encoded_kwd )
install_tool_dependencies = CheckboxField.is_checked( decoded_kwd.get( 'install_tool_dependencies', '' ) )
tsr_ids = decoded_kwd[ 'tool_shed_repository_ids' ]
tool_panel_section_keys = decoded_kwd[ 'tool_panel_section_keys' ]
repo_info_dicts = decoded_kwd[ 'repo_info_dicts' ]
filtered_repo_info_dicts = []
filtered_tool_panel_section_keys = []
repositories_for_installation = []
# Some repositories may have repository dependencies that are required to be installed before the
# dependent repository, so we'll order the list of tsr_ids to ensure all repositories install in the
# required order.
ordered_tsr_ids, ordered_repo_info_dicts, ordered_tool_panel_section_keys = \
irm.order_components_for_installation( tsr_ids,
repo_info_dicts,
tool_panel_section_keys=tool_panel_section_keys )
for tsr_id in ordered_tsr_ids:
repository = trans.install_model.context.query( trans.install_model.ToolShedRepository ) \
.get( trans.security.decode_id( tsr_id ) )
if repository.status in [ trans.install_model.ToolShedRepository.installation_status.NEW,
trans.install_model.ToolShedRepository.installation_status.UNINSTALLED ]:
repositories_for_installation.append( repository )
repo_info_dict, tool_panel_section_key = \
irm.get_repository_components_for_installation( tsr_id,
ordered_tsr_ids,
ordered_repo_info_dicts,
ordered_tool_panel_section_keys )
filtered_repo_info_dicts.append( repo_info_dict )
filtered_tool_panel_section_keys.append( tool_panel_section_key )
if repositories_for_installation:
decoded_kwd[ 'repo_info_dicts' ] = filtered_repo_info_dicts
decoded_kwd[ 'tool_panel_section_keys' ] = filtered_tool_panel_section_keys
self.install_tool_shed_repositories( trans,
repositories_for_installation,
reinstalling=reinstalling,
**decoded_kwd )
else:
kwd[ 'message' ] = 'All selected tool shed repositories are already installed.'
decoded_kwd['install_tool_dependencies'] = install_tool_dependencies
try:
tool_shed_repositories = irm.install_repositories(
tsr_ids=tsr_ids,
decoded_kwd=decoded_kwd,
reinstalling=reinstalling,
)
tsr_ids_for_monitoring = [ trans.security.encode_id( tsr.id ) for tsr in tool_shed_repositories ]
trans.response.send_redirect( web.url_for( controller='admin_toolshed',
action='monitor_repository_installation',
tool_shed_repository_ids=tsr_ids_for_monitoring ) )
except install_manager.RepositoriesInstalledException as e:
kwd[ 'message' ] = e.message
kwd[ 'status' ] = 'error'
return self.repository_installation_grid( trans, **kwd )
@@ -1092,7 +1046,7 @@ class AdminToolshed( AdminGalaxy ):
tool_path=tool_path,
tool_shed_url=tool_shed_url )
created_or_updated_tool_shed_repositories, tool_panel_section_keys, repo_info_dicts, filtered_repo_info_dicts = \
install_repository_manager.handle_tool_shed_repositories( installation_dict, using_api=False )
install_repository_manager.handle_tool_shed_repositories( installation_dict )
if created_or_updated_tool_shed_repositories:
installation_dict = dict( created_or_updated_tool_shed_repositories=created_or_updated_tool_shed_repositories,
filtered_repo_info_dicts=filtered_repo_info_dicts,
@@ -214,5 +214,5 @@ class CustomDatatypeLoader( object ):
def load_installed_display_applications( self, installed_repository_dict, deactivate=False ):
"""Load or deactivate custom datatype display applications."""
self.app.datatypes_registry.load_display_applications( installed_repository_dict=installed_repository_dict,
self.app.datatypes_registry.load_display_applications( self.app, installed_repository_dict=installed_repository_dict,
deactivate=deactivate )
+99 -50
View File
@@ -7,6 +7,7 @@ import traceback
from galaxy import exceptions
from galaxy import eggs
from galaxy import util
eggs.require( 'paramiko' )
eggs.require( 'ssh' )
@@ -454,10 +455,12 @@ class InstallRepositoryManager( object ):
def get_repository_components_for_installation( self, encoded_tsr_id, encoded_tsr_ids, repo_info_dicts,
tool_panel_section_keys ):
"""
The received encoded_tsr_ids, repo_info_dicts, and tool_panel_section_keys are 3 lists that
contain associated elements at each location in the list. This method will return the elements
from repo_info_dicts and tool_panel_section_keys associated with the received encoded_tsr_id
by determining its location in the received encoded_tsr_ids list.
The received encoded_tsr_ids, repo_info_dicts, and
tool_panel_section_keys are 3 lists that contain associated elements
at each location in the list. This method will return the elements
from repo_info_dicts and tool_panel_section_keys associated with the
received encoded_tsr_id by determining its location in the received
encoded_tsr_ids list.
"""
for index, tsr_id in enumerate( encoded_tsr_ids ):
if tsr_id == encoded_tsr_id:
@@ -621,9 +624,9 @@ class InstallRepositoryManager( object ):
self.app.datatypes_registry.load_datatype_converters( self.app.toolbox, installed_repository_dict=repository_dict )
if display_path:
# Load proprietary datatype display applications
self.app.datatypes_registry.load_display_applications( installed_repository_dict=repository_dict )
self.app.datatypes_registry.load_display_applications( self.app, installed_repository_dict=repository_dict )
def handle_tool_shed_repositories( self, installation_dict, using_api=False ):
def handle_tool_shed_repositories( self, installation_dict ):
# The following installation_dict entries are all required.
install_repository_dependencies = installation_dict[ 'install_repository_dependencies' ]
new_tool_panel_section_label = installation_dict[ 'new_tool_panel_section_label' ]
@@ -699,40 +702,36 @@ class InstallRepositoryManager( object ):
name,
owner,
changeset_revision )
installed_tool_shed_repositories = self.__install_repositories( tool_shed_url,
repository_revision_dict,
repo_info_dicts,
install_options )
installed_tool_shed_repositories = self.__initiate_and_install_repositories(
tool_shed_url,
repository_revision_dict,
repo_info_dicts,
install_options
)
return installed_tool_shed_repositories
def __install_repositories( self, tool_shed_url, repository_revision_dict, repo_info_dicts, install_options ):
# Keep track of all repositories that are installed - there may be more than one if repository dependencies are installed.
installed_tool_shed_repositories = []
def __initiate_and_install_repositories( self, tool_shed_url, repository_revision_dict, repo_info_dicts, install_options ):
try:
has_repository_dependencies = repository_revision_dict[ 'has_repository_dependencies' ]
except:
except KeyError:
raise exceptions.InternalServerError( "Tool shed response missing required parameter 'has_repository_dependencies'." )
try:
includes_tools = repository_revision_dict[ 'includes_tools' ]
except:
except KeyError:
raise exceptions.InternalServerError( "Tool shed response missing required parameter 'includes_tools'." )
try:
includes_tool_dependencies = repository_revision_dict[ 'includes_tool_dependencies' ]
except:
except KeyError:
raise exceptions.InternalServerError( "Tool shed response missing required parameter 'includes_tool_dependencies'." )
try:
includes_tools_for_display_in_tool_panel = repository_revision_dict[ 'includes_tools_for_display_in_tool_panel' ]
except:
except KeyError:
raise exceptions.InternalServerError( "Tool shed response missing required parameter 'includes_tools_for_display_in_tool_panel'." )
# Get the information about the Galaxy components (e.g., tool pane section, tool config file, etc) that will contain the repository information.
install_repository_dependencies = install_options.get( 'install_repository_dependencies', False )
install_tool_dependencies = install_options.get( 'install_tool_dependencies', False )
if install_tool_dependencies:
if self.app.config.tool_dependency_dir is None:
no_tool_dependency_dir_message = "Tool dependencies can be automatically installed only if you set "
no_tool_dependency_dir_message += "the value of your 'tool_dependency_dir' setting in your Galaxy "
no_tool_dependency_dir_message += "configuration file (galaxy.ini) and restart your Galaxy server. "
raise exceptions.ConfigDoesNotAllowException( no_tool_dependency_dir_message )
self.__assert_can_install_dependencies()
new_tool_panel_section_label = install_options.get( 'new_tool_panel_section_label', '' )
shed_tool_conf = install_options.get( 'shed_tool_conf', None )
if shed_tool_conf:
@@ -759,7 +758,7 @@ class InstallRepositoryManager( object ):
tool_shed_url=tool_shed_url )
# Create the tool_shed_repository database records and gather additional information for repository installation.
created_or_updated_tool_shed_repositories, tool_panel_section_keys, repo_info_dicts, filtered_repo_info_dicts = \
self.handle_tool_shed_repositories( installation_dict, using_api=True )
self.handle_tool_shed_repositories( installation_dict )
if created_or_updated_tool_shed_repositories:
# Build the dictionary of information necessary for installing the repositories.
installation_dict = dict( created_or_updated_tool_shed_repositories=created_or_updated_tool_shed_repositories,
@@ -778,37 +777,74 @@ class InstallRepositoryManager( object ):
tool_panel_section_keys=tool_panel_section_keys,
tool_path=tool_path,
tool_shed_url=tool_shed_url )
# Prepare the repositories for installation. Even though this method receives a single combination
# of tool_shed_url, name, owner and changeset_revision, there may be multiple repositories for installation
# at this point because repository dependencies may have added additional repositories for installation
# along with the single specified repository.
# Prepare the repositories for installation. Even though this
# method receives a single combination of tool_shed_url, name,
# owner and changeset_revision, there may be multiple repositories
# for installation at this point because repository dependencies
# may have added additional repositories for installation along
# with the single specified repository.
encoded_kwd, query, tool_shed_repositories, encoded_repository_ids = \
self.initiate_repository_installation( installation_dict )
# Some repositories may have repository dependencies that are required to be installed before the
# dependent repository, so we'll order the list of tsr_ids to ensure all repositories install in
# the required order.
# Some repositories may have repository dependencies that are
# required to be installed before the dependent repository, so
# we'll order the list of tsr_ids to ensure all repositories
# install in the required order.
tsr_ids = [ self.app.security.encode_id( tool_shed_repository.id ) for tool_shed_repository in tool_shed_repositories ]
ordered_tsr_ids, ordered_repo_info_dicts, ordered_tool_panel_section_keys = \
self.order_components_for_installation( tsr_ids, repo_info_dicts, tool_panel_section_keys=tool_panel_section_keys )
# Install the repositories, keeping track of each one for later display.
for index, tsr_id in enumerate( ordered_tsr_ids ):
tool_shed_repository = self.install_model.context.query( self.install_model.ToolShedRepository ) \
.get( self.app.security.decode_id( tsr_id ) )
if tool_shed_repository.status in [ self.install_model.ToolShedRepository.installation_status.NEW,
self.install_model.ToolShedRepository.installation_status.UNINSTALLED ]:
repo_info_dict = ordered_repo_info_dicts[ index ]
tool_panel_section_key = ordered_tool_panel_section_keys[ index ]
self.install_tool_shed_repository( tool_shed_repository,
repo_info_dict,
tool_panel_section_key,
shed_tool_conf,
tool_path,
install_tool_dependencies,
reinstalling=False )
installed_tool_shed_repositories.append( tool_shed_repository )
decoded_kwd = dict(
shed_tool_conf=shed_tool_conf,
tool_path=tool_path,
tool_panel_section_keys=tool_panel_section_keys,
repo_info_dicts=repo_info_dicts,
install_tool_dependencies=install_tool_dependencies,
)
return self.install_repositories(tsr_ids, decoded_kwd, reinstalling=False)
def install_repositories( self, tsr_ids, decoded_kwd, reinstalling ):
shed_tool_conf = decoded_kwd.get( 'shed_tool_conf', '' )
tool_path = decoded_kwd[ 'tool_path' ]
tool_panel_section_keys = util.listify( decoded_kwd[ 'tool_panel_section_keys' ] )
repo_info_dicts = util.listify( decoded_kwd[ 'repo_info_dicts' ] )
install_tool_dependencies = decoded_kwd['install_tool_dependencies']
filtered_repo_info_dicts = []
filtered_tool_panel_section_keys = []
repositories_for_installation = []
# Some repositories may have repository dependencies that are required to be installed before the
# dependent repository, so we'll order the list of tsr_ids to ensure all repositories install in the
# required order.
ordered_tsr_ids, ordered_repo_info_dicts, ordered_tool_panel_section_keys = \
self.order_components_for_installation( tsr_ids,
repo_info_dicts,
tool_panel_section_keys=tool_panel_section_keys )
for tsr_id in ordered_tsr_ids:
repository = self.install_model.context.query( self.install_model.ToolShedRepository ) \
.get( self.app.security.decode_id( tsr_id ) )
if repository.status in [ self.install_model.ToolShedRepository.installation_status.NEW,
self.install_model.ToolShedRepository.installation_status.UNINSTALLED ]:
repositories_for_installation.append( repository )
repo_info_dict, tool_panel_section_key = \
self.get_repository_components_for_installation( tsr_id,
ordered_tsr_ids,
ordered_repo_info_dicts,
ordered_tool_panel_section_keys )
filtered_repo_info_dicts.append( repo_info_dict )
filtered_tool_panel_section_keys.append( tool_panel_section_key )
installed_tool_shed_repositories = []
if repositories_for_installation:
for index, tool_shed_repository in enumerate( repositories_for_installation ):
repo_info_dict = filtered_repo_info_dicts[ index ]
tool_panel_section_key = filtered_tool_panel_section_keys[ index ]
self.install_tool_shed_repository( tool_shed_repository,
repo_info_dict=repo_info_dict,
tool_panel_section_key=tool_panel_section_key,
shed_tool_conf=shed_tool_conf,
tool_path=tool_path,
install_tool_dependencies=install_tool_dependencies,
reinstalling=reinstalling )
installed_tool_shed_repositories.append( tool_shed_repository )
else:
# We're attempting to install more than 1 repository, and all of them have already been installed.
raise exceptions.RequestParameterInvalidException( 'All repositories that you are attempting to install have been previously installed.' )
raise RepositoriesInstalledException()
return installed_tool_shed_repositories
def install_tool_shed_repository( self, tool_shed_repository, repo_info_dict, tool_panel_section_key, shed_tool_conf, tool_path,
@@ -957,6 +993,19 @@ class InstallRepositoryManager( object ):
self.install_model.context.add( tool_shed_repository )
self.install_model.context.flush()
def __assert_can_install_dependencies(self):
if self.app.config.tool_dependency_dir is None:
no_tool_dependency_dir_message = "Tool dependencies can be automatically installed only if you set "
no_tool_dependency_dir_message += "the value of your 'tool_dependency_dir' setting in your Galaxy "
no_tool_dependency_dir_message += "configuration file (galaxy.ini) and restart your Galaxy server. "
raise exceptions.ConfigDoesNotAllowException( no_tool_dependency_dir_message )
class RepositoriesInstalledException(exceptions.RequestParameterInvalidException):
def __init__(self):
super(RepositoriesInstalledException, self).__init__('All repositories that you are attempting to install have been previously installed.')
def fetch_tool_versions( app, tool_shed_repository ):
""" Fetch a data structure describing tool shed versions from the tool shed
@@ -523,7 +523,7 @@ class ToolMigrationManager( object ):
installed_repository_dict=repository_dict )
if display_path:
# Load proprietary datatype display applications
self.app.datatypes_registry.load_display_applications( installed_repository_dict=repository_dict )
self.app.datatypes_registry.load_display_applications( self.app, installed_repository_dict=repository_dict )
basic_util.remove_dir( work_dir )
def install_repository( self, repository_elem, tool_shed_repository, install_dependencies, is_repository_dependency=False ):
+1 -1
View File
@@ -108,7 +108,7 @@ define(['utils/utils', 'utils/deferred', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc',
var new_state = self.tree.finalize();
if (!_.isEqual(new_state, current_state)) {
current_state = new_state;
self._updateModel($.extend({}, current_state));
self._updateModel($.extend(true, {}, current_state));
}
});
});
@@ -1 +1 @@
define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-section","mvc/tools/tools-tree"],function(f,g,e,j,h,a,d,c,i,b){return Backbone.View.extend({initialize:function(k){this.optionsDefault={is_dynamic:true,narrow:false,initial_errors:false,cls_portlet:"ui-portlet-limited"};this.options=f.merge(k,this.optionsDefault);console.debug(this.options);var l=parent.Galaxy;if(l&&l.modal){this.modal=l.modal}else{this.modal=new j.Modal.View()}if(l&&l.currUser){this.is_admin=l.currUser.get("is_admin")}else{this.is_admin=false}this.container=this.options.container||"body";this.deferred=new g();this.setElement("<div/>");$(this.container).append(this.$el);this.build(this.options)},build:function(m){var k=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.history={};k.options.inputs=m&&m.inputs;this._renderForm(m);var l=this.tree.finalize();if(m.initial_errors){this._errors(m)}this.on("refresh",function(){k.deferred.reset();k.deferred.execute(function(){var n=k.tree.finalize();if(!_.isEqual(n,l)){l=n;k._updateModel($.extend({},l))}})});this.on("reset",function(){for(var n in this.element_list){this.element_list[n].reset()}})},reciept:function(k){$(this.container).empty();$(this.container).append(k)},highlight:function(l,m,k){var n=this.element_list[l];if(n){n.error(m||"Please verify this parameter.");if(!k){$("html, body").animate({scrollTop:n.$el.offset().top-20},500)}}},_errors:function(m){this.trigger("reset");if(m&&m.errors){var n=this.tree.matchResponse(m.errors);for(var l in this.element_list){var k=this.element_list[l];if(n[l]){this.highlight(l,n[l],true)}}}},_renderForm:function(s){var r=this;this.message=new j.Message();var l=new j.ButtonMenu({icon:"fa-cubes",title:(!s.narrow&&"Versions")||null,tooltip:"Select another tool version"});if(s.versions&&s.versions.length>1){for(var n in s.versions){var p=s.versions[n];if(p!=s.version){l.addMenu({title:"Switch to "+p,version:p,icon:"fa-cube",onclick:function(){r.options.id=r.options.id.replace(r.options.version,this.version);r.options.version=this.version;r.deferred.reset();r.deferred.execute(function(){r._buildModel()})}})}}}else{l.$el.hide()}var o=new j.ButtonMenu({icon:"fa-caret-down",title:(!s.narrow&&"Options")||null,tooltip:"View available options"});if(s.biostar_url){o.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(s.biostar_url+"/p/new/post/")}});o.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(s.biostar_url+"/t/"+s.id+"/")}})}o.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+s.id)}});if(this.is_admin){o.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+s.id+"/download"}})}if(s.requirements&&s.requirements.length>0){o.addMenu({icon:"fa-info-circle",title:"Requirements",tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;r.message.update({persistent:true,message:c.requirements(s),status:"info"})}else{this.visible=false;r.message.update({message:""})}}})}if(this.options.sharable_url){o.addMenu({icon:"fa-external-link",title:"See in Tool Shed",tooltip:"Access the repository",onclick:function(){window.open(r.options.sharable_url)}})}this.section=new i.View(r,{inputs:s.inputs});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new e.View({icon:"fa-wrench",title:"<b>"+s.name+"</b> "+s.description+" (Galaxy Tool Version "+s.version+")",cls:this.options.cls_portlet,operations:{menu:o,versions:l},buttons:this.buttons});this.portlet.append(this.message.$el.addClass("ui-margin-top"));this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(s.help!=""){this.$el.append(c.help(s.help))}if(s.citations){var q=$("<div/>");var k=new h.ToolCitationCollection();k.tool_id=s.id;var m=new a.CitationListView({el:q,collection:k});m.render();k.fetch();this.$el.append(q)}if(s.message){this.message.update({persistent:true,status:"warning",message:s.message})}console.debug("tools-form-base::initialize() - Completed.")}})});
define(["utils/utils","utils/deferred","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-section","mvc/tools/tools-tree"],function(f,g,e,j,h,a,d,c,i,b){return Backbone.View.extend({initialize:function(k){this.optionsDefault={is_dynamic:true,narrow:false,initial_errors:false,cls_portlet:"ui-portlet-limited"};this.options=f.merge(k,this.optionsDefault);console.debug(this.options);var l=parent.Galaxy;if(l&&l.modal){this.modal=l.modal}else{this.modal=new j.Modal.View()}if(l&&l.currUser){this.is_admin=l.currUser.get("is_admin")}else{this.is_admin=false}this.container=this.options.container||"body";this.deferred=new g();this.setElement("<div/>");$(this.container).append(this.$el);this.build(this.options)},build:function(m){var k=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.history={};k.options.inputs=m&&m.inputs;this._renderForm(m);var l=this.tree.finalize();if(m.initial_errors){this._errors(m)}this.on("refresh",function(){k.deferred.reset();k.deferred.execute(function(){var n=k.tree.finalize();if(!_.isEqual(n,l)){l=n;k._updateModel($.extend(true,{},l))}})});this.on("reset",function(){for(var n in this.element_list){this.element_list[n].reset()}})},reciept:function(k){$(this.container).empty();$(this.container).append(k)},highlight:function(l,m,k){var n=this.element_list[l];if(n){n.error(m||"Please verify this parameter.");if(!k){$("html, body").animate({scrollTop:n.$el.offset().top-20},500)}}},_errors:function(m){this.trigger("reset");if(m&&m.errors){var n=this.tree.matchResponse(m.errors);for(var l in this.element_list){var k=this.element_list[l];if(n[l]){this.highlight(l,n[l],true)}}}},_renderForm:function(s){var r=this;this.message=new j.Message();var l=new j.ButtonMenu({icon:"fa-cubes",title:(!s.narrow&&"Versions")||null,tooltip:"Select another tool version"});if(s.versions&&s.versions.length>1){for(var n in s.versions){var p=s.versions[n];if(p!=s.version){l.addMenu({title:"Switch to "+p,version:p,icon:"fa-cube",onclick:function(){r.options.id=r.options.id.replace(r.options.version,this.version);r.options.version=this.version;r.deferred.reset();r.deferred.execute(function(){r._buildModel()})}})}}}else{l.$el.hide()}var o=new j.ButtonMenu({icon:"fa-caret-down",title:(!s.narrow&&"Options")||null,tooltip:"View available options"});if(s.biostar_url){o.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(s.biostar_url+"/p/new/post/")}});o.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(s.biostar_url+"/t/"+s.id+"/")}})}o.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+s.id)}});if(this.is_admin){o.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+s.id+"/download"}})}if(s.requirements&&s.requirements.length>0){o.addMenu({icon:"fa-info-circle",title:"Requirements",tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;r.message.update({persistent:true,message:c.requirements(s),status:"info"})}else{this.visible=false;r.message.update({message:""})}}})}if(this.options.sharable_url){o.addMenu({icon:"fa-external-link",title:"See in Tool Shed",tooltip:"Access the repository",onclick:function(){window.open(r.options.sharable_url)}})}this.section=new i.View(r,{inputs:s.inputs});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new e.View({icon:"fa-wrench",title:"<b>"+s.name+"</b> "+s.description+" (Galaxy Tool Version "+s.version+")",cls:this.options.cls_portlet,operations:{menu:o,versions:l},buttons:this.buttons});this.portlet.append(this.message.$el.addClass("ui-margin-top"));this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(s.help!=""){this.$el.append(c.help(s.help))}if(s.citations){var q=$("<div/>");var k=new h.ToolCitationCollection();k.tool_id=s.id;var m=new a.CitationListView({el:q,collection:k});m.render();k.fetch();this.$el.append(q)}if(s.message){this.message.update({persistent:true,status:"warning",message:s.message})}console.debug("tools-form-base::initialize() - Completed.")}})});
@@ -1,3 +1,3 @@
<input type="text" name="query" value="{{search_hint_string}}" id="tool-search-query" autocomplete="off" class="search-query parent-width" />
<input type="text" name="query" placeholder="{{search_hint_string}}" id="tool-search-query" autocomplete="off" class="search-query parent-width" />
<a id="search-clear-btn" title="clear search (esc)"> </a>
<img src="{{spinner_url}}" id="search-spinner" class="search-spinner"/>
<img src="{{spinner_url}}" id="search-spinner" class="search-spinner"/>
@@ -1,4 +1,4 @@
#site_id site_name site_url dbkey ivg_build_name
web_link_main web current http://www.broadinstitute.org/igv/projects/current/igv.php hg19,hg_g1k_v37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum hg19,b37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum
web_link_main web current http://www.broadinstitute.org/igv/projects/current/igv.php hg_g1k_v37 b37
#web_jnlp_1.5 web 1.5 http://www.broadinstitute.org/igvdata/jws/prod hg19,hg_g1k_v37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum hg19,b37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum
#local_default local http://localhost:60151/load hg19,hg_g1k_v37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum hg19,b37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum
#local_default local http://localhost:60151/load hg19,hg_g1k_v37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum hg19,b37,hg18,1kg_ref,hg17,hg16,mm9,mm8,mm7,panTro2,rheMac2,rn4,canFam2,bosTau6,bosTau4,bosTau3,susScrofa,galGal3,cavPor3,monDom5,xenTro2,taeGut1,zebrafish,danRer6,danRer7,gasAcu1,Aplysia,Plasmodium_3D7_v2.1,Plasmodium_3D7_v5.5,Plasmodium_6.1,PlasmoDB_7.0,pvivax,GSM552910,sacCer1,sacCer2,sk1,Y55,sacCer62,spombe_709,spombe_1.55,candida,mg8,spur_2.1,spur_2.5,spur_3.0,WS201,ce6,ce4,dm3,dm2,dmel_5.9,dmel_r5.22,dmel_r5.33,tcas_2.0,tcas_3.0,ncrassa_v3,nc10,Glamblia_2.0,me49,tb927,tbgambi,lmjr,anidulans_4.1,NC_009012,U00096.2,NC_000913.2,NC_002655.2,CSavignyi_v2.1,tair8,tair9,tair10,O_Sativa_r6,osativa_6.1,B73,ZmB73_5a,ppatens_1.2,D.discoideum