Merging with dev

This commit is contained in:
anuprulez
2017-07-05 23:30:35 +02:00
133 changed files with 1009 additions and 1052 deletions
+13 -80
View File
@@ -9,72 +9,15 @@ lib/galaxy/actions/
lib/galaxy/auth/
lib/galaxy/config.py
lib/galaxy/containers/
lib/galaxy/dataset_collections/builder.py
lib/galaxy/dataset_collections/__init__.py
lib/galaxy/dataset_collections/structure.py
lib/galaxy/dataset_collections/subcollections.py
lib/galaxy/dataset_collections/type_description.py
lib/galaxy/dataset_collections/types/__init__.py
lib/galaxy/datatypes/assembly.py
lib/galaxy/datatypes/binary.py
lib/galaxy/datatypes/checkers.py
lib/galaxy/datatypes/constructive_solid_geometry.py
lib/galaxy/datatypes/converters/bcf_bgzip_to_bcf_converter.py
lib/galaxy/datatypes/converters/bcf_to_bcf_bgzip_converter.py
lib/galaxy/datatypes/converters/bedgraph_to_array_tree_converter.py
lib/galaxy/datatypes/converters/bed_to_gff_converter.py
lib/galaxy/datatypes/converters/bgzip.py
lib/galaxy/datatypes/converters/fasta_to_len.py
lib/galaxy/datatypes/converters/fastqsolexa_to_fasta_converter.py
lib/galaxy/datatypes/converters/fastqsolexa_to_qual_converter.py
lib/galaxy/datatypes/converters/fastq_to_fqtoc.py
lib/galaxy/datatypes/converters/gff_to_bed_converter.py
lib/galaxy/datatypes/converters/gff_to_interval_index_converter.py
lib/galaxy/datatypes/converters/__init__.py
lib/galaxy/datatypes/converters/interval_to_bed_converter.py
lib/galaxy/datatypes/converters/interval_to_bedstrict_converter.py
lib/galaxy/datatypes/converters/interval_to_coverage.py
lib/galaxy/datatypes/converters/interval_to_fli.py
lib/galaxy/datatypes/converters/interval_to_interval_index_converter.py
lib/galaxy/datatypes/converters/interval_to_tabix_converter.py
lib/galaxy/datatypes/converters/lped_to_fped_converter.py
lib/galaxy/datatypes/converters/lped_to_pbed_converter.py
lib/galaxy/datatypes/converters/maf_to_fasta_converter.py
lib/galaxy/datatypes/converters/maf_to_interval_converter.py
lib/galaxy/datatypes/converters/pbed_to_lped_converter.py
lib/galaxy/datatypes/converters/picard_interval_list_to_bed6_converter.py
lib/galaxy/datatypes/converters/pileup_to_interval_index_converter.py
lib/galaxy/datatypes/converters/tabular_to_dbnsfp.py
lib/galaxy/datatypes/converters/vcf_to_vcf_bgzip.py
lib/galaxy/datatypes/converters/wiggle_to_array_tree_converter.py
lib/galaxy/datatypes/coverage.py
lib/galaxy/datatypes/dataproviders/base.py
lib/galaxy/datatypes/dataproviders/exceptions.py
lib/galaxy/datatypes/dataproviders/__init__.py
lib/galaxy/datatypes/data.py
lib/galaxy/datatypes/display_applications/__init__.py
lib/galaxy/datatypes/display_applications/util.py
lib/galaxy/datatypes/genetics.py
lib/galaxy/datatypes/images.py
lib/galaxy/datatypes/__init__.py
lib/galaxy/datatypes/interval.py
lib/galaxy/datatypes/metadata.py
lib/galaxy/datatypes/msa.py
lib/galaxy/datatypes/ngsindex.py
lib/galaxy/datatypes/proteomics.py
lib/galaxy/datatypes/registry.py
lib/galaxy/datatypes/sequence.py
lib/galaxy/datatypes/tabular.py
lib/galaxy/datatypes/text.py
lib/galaxy/datatypes/tracks.py
lib/galaxy/datatypes/util/
lib/galaxy/dataset_collections/
lib/galaxy/datatypes/
lib/galaxy/dependencies/
lib/galaxy/eggs/
lib/galaxy/exceptions/__init__.py
lib/galaxy/exceptions/
lib/galaxy/external_services/__init__.py
lib/galaxy/external_services/parameters.py
lib/galaxy/external_services/result_handlers/basic.py
lib/galaxy/external_services/result_handlers/__init__.py
lib/galaxy_ext/
lib/galaxy/forms/__init__.py
lib/galaxy/jobs/actions/
lib/galaxy/jobs/command_factory.py
@@ -113,15 +56,7 @@ lib/galaxy/managers/lddas.py
lib/galaxy/managers/libraries.py
lib/galaxy/managers/secured.py
lib/galaxy/managers/taggable.py
lib/galaxy/model/__init__.py
lib/galaxy/model/item_attrs.py
lib/galaxy/model/mapping.py
lib/galaxy/model/metadata.py
lib/galaxy/model/migrate/
lib/galaxy/model/orm/
lib/galaxy/model/tool_shed_install/migrate/__init__.py
lib/galaxy/model/tool_shed_install/migrate/versions/
lib/galaxy/model/util.py
lib/galaxy/model/
lib/galaxy/objectstore/pulsar.py
lib/galaxy/objectstore/s3_multipart_upload.py
lib/galaxy/openid/__init__.py
@@ -129,7 +64,7 @@ lib/galaxy/quota/
lib/galaxy/sample_tracking/data_transfer.py
lib/galaxy/sample_tracking/__init__.py
lib/galaxy/sample_tracking/sample.py
lib/galaxy/security/validate_user_input.py
lib/galaxy/security/
lib/galaxy/tags/
lib/galaxy/tools/
lib/galaxy/util/
@@ -174,6 +109,7 @@ lib/galaxy/webapps/galaxy/api/samples.py
lib/galaxy/webapps/galaxy/api/tools.py
lib/galaxy/webapps/galaxy/api/tours.py
lib/galaxy/webapps/galaxy/api/workflows.py
lib/galaxy/webapps/galaxy/config_watchers.py
lib/galaxy/webapps/galaxy/controllers/async.py
lib/galaxy/webapps/galaxy/controllers/data_manager.py
lib/galaxy/webapps/galaxy/controllers/error.py
@@ -186,7 +122,6 @@ lib/galaxy/webapps/galaxy/controllers/requests.py
lib/galaxy/webapps/galaxy/controllers/search.py
lib/galaxy/webapps/galaxy/controllers/tool_runner.py
lib/galaxy/webapps/galaxy/controllers/userskeys.py
lib/galaxy/webapps/galaxy/config_watchers.py
lib/galaxy/webapps/galaxy/__init__.py
lib/galaxy/webapps/__init__.py
lib/galaxy/webapps/reports/config.py
@@ -209,13 +144,11 @@ lib/galaxy/webapps/tool_shed/util/__init__.py
lib/galaxy/webapps/tool_shed/util/ratings_util.py
lib/galaxy/webapps/tool_shed/util/shed_statistics.py
lib/galaxy/webapps/util.py
lib/galaxy/workflow/extract.py
lib/galaxy/workflow/__init__.py
lib/galaxy/workflow/render.py
lib/galaxy/workflow/run.py
lib/galaxy/workflow/schedulers/
lib/galaxy/workflow/steps.py
lib/galaxy/work/__init__.py
lib/galaxy/webhooks/
lib/galaxy/work/
lib/galaxy/workflow/
lib/galaxy_ext/
lib/log_tempfile.py
lib/mimeparse.py
lib/psyco_full.py
lib/tool_shed/
@@ -366,6 +299,7 @@ test/unit/shed_unit/test_fabric_util.py
test/unit/shed_unit/test_td_common_util.py
test/unit/test_galaxy_transactions.py
test/unit/test_lazy_process.py
test/unit/test_objectstore.py
test/unit/test_routes.py
test/unit/test_security_helper.py
test/unit/test_sockets.py
@@ -393,6 +327,5 @@ test/unit/web/base/__init__.py
test/unit/web/framework/__init__.py
test/unit/web/__init__.py
test/unit/workflows/
test/unit/test_objectstore.py
tool_list.py
tools/
+4 -27
View File
@@ -8,23 +8,7 @@ lib/galaxy/auth/
lib/galaxy/config.py
lib/galaxy/containers/
lib/galaxy/dataset_collections/
lib/galaxy/datatypes/assembly.py
lib/galaxy/datatypes/binary.py
lib/galaxy/datatypes/constructive_solid_geometry.py
lib/galaxy/datatypes/converters/
lib/galaxy/datatypes/dataproviders/
lib/galaxy/datatypes/data.py
lib/galaxy/datatypes/genetics.py
lib/galaxy/datatypes/images.py
lib/galaxy/datatypes/interval.py
lib/galaxy/datatypes/msa.py
lib/galaxy/datatypes/ngsindex.py
lib/galaxy/datatypes/proteomics.py
lib/galaxy/datatypes/registry.py
lib/galaxy/datatypes/sequence.py
lib/galaxy/datatypes/sniff.py
lib/galaxy/datatypes/tabular.py
lib/galaxy/datatypes/tracks.py
lib/galaxy/datatypes/
lib/galaxy/dependencies/
lib/galaxy/eggs/
lib/galaxy/exceptions/
@@ -32,12 +16,7 @@ lib/galaxy/external_services/
lib/galaxy/forms/
lib/galaxy/jobs/
lib/galaxy/managers/
lib/galaxy/model/__init__.py
lib/galaxy/model/item_attrs.py
lib/galaxy/model/mapping.py
lib/galaxy/model/metadata.py
lib/galaxy/model/migrate/
lib/galaxy/model/orm/now.py
lib/galaxy/model/
lib/galaxy/objectstore/
lib/galaxy/openid/
lib/galaxy/quota/
@@ -69,11 +48,9 @@ lib/galaxy/webapps/tool_shed/controllers/user.py
lib/galaxy/webapps/tool_shed/framework/middleware/remoteuser.py
lib/galaxy/webapps/tool_shed/__init__.py
lib/galaxy/webapps/tool_shed/util/ratings_util.py
lib/galaxy/webhooks/
lib/galaxy/work/
lib/galaxy/workflow/extract.py
lib/galaxy/workflow/run.py
lib/galaxy/workflow/schedulers/
lib/galaxy/workflow/steps.py
lib/galaxy/workflow/
lib/galaxy_ext/
lib/log_tempfile.py
lib/psyco_full.py
+1
View File
@@ -17,6 +17,7 @@ database/files
database/jobs_directory
database/job_working_directory
database/pbs
database/test_errors
database/tmp
database/*.sqlite
database/openid_consumer_cache
+3 -3
View File
@@ -90,7 +90,7 @@ window.app = function app( options, bootstrapped ){
'(/)pages(/)(:action_id)' : 'show_pages',
'(/)visualizations/list_published(/)' : 'show_visualizations',
'(/)workflows/list_published(/)' : 'show_workflows_published',
'(/)histories(/)list(/)' : 'show_histories',
'(/)histories(/)(:action_id)' : 'show_histories',
'(/)datasets(/)list(/)' : 'show_datasets',
'(/)workflow/configure_menu(/)' : 'show_configure_menu',
'(/)workflow/import_workflow' : 'show_import_workflow',
@@ -136,8 +136,8 @@ window.app = function app( options, bootstrapped ){
this.page.display( new GridView( { url_base: Galaxy.root + 'workflow/list_published', dict_format: true } ) );
},
show_histories : function() {
this.page.display( new HistoryList.View() );
show_histories : function( action_id ) {
this.page.display( new HistoryList.View( { action_id: action_id } ) );
},
show_datasets : function() {
+33 -21
View File
@@ -221,28 +221,40 @@ var Collection = Backbone.Collection.extend({
//
// User tab.
//
var userTab = {};
if ( !Galaxy.user.id ){
var userTab = {
id : 'user',
title : _l('Login or Register'),
cls : 'loggedout-only',
tooltip : _l('Account registration or login'),
menu : [{
title : _l('Login'),
url : 'user/login',
target : 'galaxy_main',
noscratchbook : true
}]
};
options.allow_user_creation && userTab.menu.push({
title : _l('Register'),
url : 'user/create',
target : 'galaxy_main',
noscratchbook : true
});
this.add( userTab );
if ( options.allow_user_creation ) {
userTab = {
id : 'user',
title : _l('Login or Register'),
cls : 'loggedout-only',
tooltip : _l('Account registration or login'),
menu : [{
title : _l('Login'),
url : 'user/login',
target : 'galaxy_main',
noscratchbook : true
}, {
title: _l('Register'),
url: 'user/create',
target: 'galaxy_main',
noscratchbook: true
}
]
};
} else {
userTab = {
id: 'user',
title: _l('Login'),
cls: 'loggedout-only',
tooltip: _l('Login'),
url: 'user/login',
target: 'galaxy_main',
noscratchbook: true
};
}
} else {
var userTab = {
userTab = {
id : 'user',
title : _l('User'),
cls : 'loggedin-only',
@@ -290,8 +302,8 @@ var Collection = Backbone.Collection.extend({
target : '_top'
}]
};
this.add( userTab );
}
this.add( userTab );
var activeView = this.get( options.active_view );
activeView && activeView.set( 'active', true );
return new jQuery.Deferred().resolve().promise();
@@ -285,7 +285,7 @@ var DatasetCollection = Backbone.Model
// ........................................................................ searchable
/** searchable attributes for collections */
searchAttributes : [
'name'
'name', 'tags'
],
// ........................................................................ misc
@@ -7,7 +7,7 @@ define( [ 'utils/utils', 'mvc/grid/grid-view', 'mvc/history/history-model', 'mvc
this.setElement( $( '<div/>' ) );
this.model = new Backbone.Model();
Utils.get({
url : Galaxy.root + 'history/list',
url : Galaxy.root + 'history/' + options.action_id,
success : function( response ) {
response[ 'dict_format' ] = true;
_.each( response[ 'operations' ], function( operation ) {
@@ -22,9 +22,9 @@ var menu = [
},
{
html : _l( 'Histories Shared with Me' ),
href : 'history/list_shared'
href : 'histories/list_shared',
target : '_top'
},
{
html : _l( 'Current History' ),
header : true,
@@ -66,14 +66,23 @@ define( [ 'utils/utils', 'utils/deferred', 'mvc/ui/ui-misc', 'mvc/form/form-view
// build request url
var build_url = '';
var build_data = {};
var job_id = '';
// When re-running a job the job_id is found in the new_options object.
// When re-running a job and requesting a new tool_version,
// the job_id is in the options object.
if ( new_options.job_id ) {
build_url = Galaxy.root + 'api/jobs/' + new_options.job_id + '/build_for_rerun';
job_id = new_options.job_id;
} else if (options.job_id) {
job_id = options.job_id;
}
if ( job_id ) {
build_url = Galaxy.root + 'api/jobs/' + job_id + '/build_for_rerun';
} else {
build_url = Galaxy.root + 'api/tools/' + options.id + '/build';
build_data = $.extend( {}, Galaxy.params );
build_data[ 'tool_id' ] && ( delete build_data[ 'tool_id' ] );
options.version && ( build_data[ 'tool_version' ] = options.version );
}
options.version && ( build_data[ 'tool_version' ] = options.version );
// get initial model
Utils.get({
-1
View File
@@ -796,7 +796,6 @@
margin-right: 5px;
}
.ui-color-picker-label {
float: left;
line-height: 1.2em;
margin-bottom: 5px;
}
+2
View File
@@ -608,6 +608,7 @@
<datatype extension="ptaligntrimmedca" type="galaxy.datatypes.plant_tribes:PlantTribesMultipleSequenceAlignmentTrimmedCodonAlignment" />
<datatype extension="ptalignfiltered" type="galaxy.datatypes.plant_tribes:PlantTribesMultipleSequenceAlignmentFiltered" />
<datatype extension="ptalignfilteredca" type="galaxy.datatypes.plant_tribes:PlantTribesMultipleSequenceAlignmentFilteredCodonAlignment" />
<datatype extension="ptkscmp" type="galaxy.datatypes.plant_tribes:PlantTribesKsComponents" display_in_upload="true"/>
<datatype extension="ptortho" type="galaxy.datatypes.plant_tribes:PlantTribesOrtho" />
<datatype extension="ptorthocs" type="galaxy.datatypes.plant_tribes:PlantTribesOrthoCodingSequence" />
<datatype extension="ptphylip" type="galaxy.datatypes.plant_tribes:PlantTribesPhylip" />
@@ -623,6 +624,7 @@
defined format first, followed by next-most rigidly defined,
and so on.
-->
<sniffer type="galaxy.datatypes.plant_tribes:PlantTribesKsComponents"/>
<sniffer type="galaxy.datatypes.plant_tribes:Smat"/>
<sniffer type="galaxy.datatypes.mothur:Sabund"/>
<sniffer type="galaxy.datatypes.mothur:Otu"/>
-2
View File
@@ -926,11 +926,9 @@ class ConfiguresGalaxyMixin:
from galaxy import tools
from galaxy.managers.citations import CitationsManager
from galaxy.tools.deps import containers
from galaxy.tools.toolbox.lineages.tool_shed import ToolVersionCache
import galaxy.tools.search
self.citations_manager = CitationsManager( self )
self.tool_version_cache = ToolVersionCache(self)
self._toolbox_lock = threading.RLock()
# Initialize the tools, making sure the list of tool configs includes the reserved migrated_tools_conf.xml file.
+9 -5
View File
@@ -1,6 +1,10 @@
from galaxy.util import bunch
from galaxy import exceptions
from .structure import get_structure, leaf
from galaxy.util import bunch
from .structure import (
get_structure,
leaf
)
CANNOT_MATCH_ERROR_MESSAGE = "Cannot match collection types."
@@ -23,8 +27,8 @@ class CollectionsToMatch( object ):
def has_collections( self ):
return len( self.collections ) > 0
def iteritems( self ):
return self.collections.iteritems()
def items( self ):
return self.collections.items()
class MatchingCollections( object ):
@@ -71,7 +75,7 @@ class MatchingCollections( object ):
return None
matching_collections = MatchingCollections()
for input_key, to_match in collections_to_match.iteritems():
for input_key, to_match in collections_to_match.items():
hdca = to_match.hdca
collection_type_description = collection_type_descriptions.for_collection_type( hdca.collection.collection_type )
subcollection_type = to_match.subcollection_type
+5 -2
View File
@@ -1,7 +1,10 @@
from .types import list
from .types import paired
from galaxy import model
from .types import (
list,
paired
)
PLUGIN_CLASSES = [list.ListDatasetCollectionType, paired.PairedDatasetCollectionType]
+1 -1
View File
@@ -124,7 +124,7 @@ class Tree( object ):
def dict_map( func, input_dict ):
return dict( [ ( k, func(v) ) for k, v in input_dict.items() ] )
return dict( ( k, func(v) ) for k, v in input_dict.items() )
def get_structure( dataset_collection_instance, collection_type_description, leaf_subcollection_type=None ):
+3 -3
View File
@@ -1,7 +1,7 @@
from ..types import BaseDatasetCollectionType
from galaxy.model import DatasetCollectionElement
from ..types import BaseDatasetCollectionType
class ListDatasetCollectionType( BaseDatasetCollectionType ):
""" A flat list of named elements.
@@ -12,7 +12,7 @@ class ListDatasetCollectionType( BaseDatasetCollectionType ):
pass
def generate_elements( self, elements ):
for identifier, element in elements.iteritems():
for identifier, element in elements.items():
association = DatasetCollectionElement(
element=element,
element_identifier=identifier,
@@ -1,7 +1,7 @@
from ..types import BaseDatasetCollectionType
from galaxy.model import DatasetCollectionElement, HistoryDatasetAssociation
from ..types import BaseDatasetCollectionType
FORWARD_IDENTIFIER = "forward"
REVERSE_IDENTIFIER = "reverse"
+6 -4
View File
@@ -30,14 +30,16 @@
Covers the ``blastxml`` format and the BLAST databases.
"""
import logging
import os
from time import sleep
from galaxy.datatypes.data import get_file_peek
from galaxy.datatypes.data import Data, Text
from galaxy.datatypes.xml import GenericXml
from .data import (
Data,
get_file_peek,
Text
)
from .xml import GenericXml
log = logging.getLogger(__name__)
+1 -1
View File
@@ -1,7 +1,7 @@
from __future__ import absolute_import
import galaxy.datatypes.tabular
import galaxy.datatypes.metadata
import galaxy.datatypes.tabular
from galaxy.datatypes.metadata import MetadataElement
@@ -5,18 +5,19 @@ from __future__ import division
import sys
from bx.arrays.array_tree import array_tree_dict_from_reader, FileArrayTreeDict
from six import Iterator
BLOCK_SIZE = 100
class BedGraphReader:
class BedGraphReader(Iterator):
def __init__( self, f ):
self.f = f
def __iter__( self ):
return self
def next( self ):
def __next__( self ):
while True:
line = self.f.readline()
if not line:
@@ -46,7 +47,7 @@ def main():
# Fill array from reader
d = array_tree_dict_from_reader( reader, {}, block_size=BLOCK_SIZE )
for array_tree in d.itervalues():
for array_tree in d.values():
array_tree.root.build_summary()
FileArrayTreeDict.dict_to_file( d, open( out_fname, "w" ) )
@@ -10,9 +10,8 @@
Input: fasta
Output: tabular
"""
import sys
import os
import sys
seq_hash = {}
@@ -89,7 +89,7 @@ def main():
out = open( out_fname, 'w' )
max_len = 0
entries = []
for name in sorted( name_loc_dict.iterkeys() ):
for name in sorted( name_loc_dict.keys() ):
loc = name_loc_dict[ name ]
entry = '%s\t%s\t%s' % ( name.lower(), name, '%s:%i-%i' % ( loc[ 'contig' ], loc[ 'start' ], loc[ 'end' ] ) )
if len( entry ) > max_len:
@@ -3,9 +3,9 @@
from __future__ import print_function
import os
import subprocess
import sys
import tempfile
import subprocess
import time
prog = "pbed_ldreduced_converter.py"
@@ -4,9 +4,8 @@ convert a ref.taxonomy file to a seq.taxonomy file
Usage:
%python ref_to_seq_taxonomy_converter.py <ref.taxonom> <seq.taxonomy>
"""
import sys
import re
import sys
assert sys.version_info[:2] >= (2, 4)
@@ -5,12 +5,12 @@
A wrapper script for converting SAM to BAM, with sorting.
%prog input_filename.sam output_filename.bam
"""
import os
import sys
import optparse
import tempfile
import subprocess
import os
import shutil
import subprocess
import sys
import tempfile
from distutils.version import LooseVersion
CHUNK_SIZE = 2 ** 20 # 1mb
@@ -1,5 +1,4 @@
#!/usr/bin/env python
"""
Convert from VCF file to interval index file.
"""
@@ -7,9 +6,8 @@ from __future__ import division
import optparse
from bx.interval_index_file import Indexes
import galaxy_utils.sequence.vcf
from bx.interval_index_file import Indexes
def main():
@@ -20,7 +20,7 @@ def main():
# Fill array from reader
d = array_tree_dict_from_reader( reader, {}, block_size=BLOCK_SIZE )
for array_tree in d.itervalues():
for array_tree in d.values():
array_tree.root.build_summary()
FileArrayTreeDict.dict_to_file( d, open( out_fname, "w" ) )
@@ -11,7 +11,10 @@ import sys
import bx.wiggle
from galaxy.util.ucsc import UCSCOutWrapper, UCSCLimitException
from galaxy.util.ucsc import (
UCSCLimitException,
UCSCOutWrapper
)
def stop_err( msg ):
-23
View File
@@ -22,29 +22,6 @@ class LastzCoverage( Tabular ):
MetadataElement( name="reverseCol", desc="Optional reverse read column", param=metadata.ColumnParameter, optional=True, no_value=0 )
MetadataElement( name="columns", default=3, desc="Number of columns", readonly=True, visible=False )
def get_track_window(self, dataset, data, start, end):
"""
Assumes we have a numpy file.
"""
# Maybe if we import here people will still be able to use Galaxy when numpy kills it
import numpy
range = end - start
# Determine appropriate resolution to plot ~1000 points
resolution = ( 10 ** math.ceil( math.log10( range / 1000 ) ) )
# Restrict to valid range
resolution = min( resolution, 10000 )
resolution = max( resolution, 1 )
# Memory map the array (don't load all the data)
data = numpy.load( data )
# Grab just what we need
t_start = math.floor( start / resolution )
t_end = math.ceil( end / resolution )
x = numpy.arange( t_start, t_end ) * resolution
y = data[ t_start : t_end ]
return zip(x.tolist(), y.tolist())
def get_track_resolution( self, dataset, start, end):
range = end - start
# Determine appropriate resolution to plot ~1000 points
+1 -4
View File
@@ -1054,8 +1054,7 @@ def get_file_peek( file_name, is_multi_byte=False, WIDTH=256, LINE_COUNT=5, skip
count = 0
file_type = None
data_checked = False
temp = compression_utils.get_fileobj( file_name, "U" )
try:
with compression_utils.get_fileobj( file_name, "U" ) as temp:
while count < LINE_COUNT:
line = temp.readline( WIDTH )
if line and not is_multi_byte and not data_checked:
@@ -1083,8 +1082,6 @@ def get_file_peek( file_name, is_multi_byte=False, WIDTH=256, LINE_COUNT=5, skip
if not skip_line:
lines.append( line )
count += 1
finally:
temp.close()
if file_type == 'binary':
text = "%s file" % file_type
else:
+7 -5
View File
@@ -4,16 +4,18 @@ Chunk (N number of bytes at M offset to a source's beginning) provider.
Primarily for file sources but usable by any iterator that has both
seek and read( N ).
"""
import os
import base64
import base
import exceptions
import logging
import os
from . import (
base,
exceptions
)
log = logging.getLogger( __name__ )
# -----------------------------------------------------------------------------
class ChunkDataProvider( base.DataProvider ):
"""
Data provider that yields chunks of data from its file.
+2 -2
View File
@@ -2,9 +2,10 @@
Providers that provide lists of lists generally where each line of a source
is further subdivided into multiple data (e.g. columns from a line).
"""
import logging
import re
from six.moves.urllib.parse import unquote_plus
import re
from . import line
@@ -15,7 +16,6 @@ TransposedColumnarDataProvider: provides each column as a single array
- see existing visualizations/dataprovider/basic.ColumnDataProvider
"""
import logging
log = logging.getLogger( __name__ )
+17 -13
View File
@@ -5,18 +5,23 @@ Dataproviders that use either:
- or provide data in some way relevant to bioinformatic data
(e.g. parsing genomic regions from their source)
"""
import base
import line
import column
import external
from galaxy.util import sqlite
import logging
import sys
from bx import seq as bx_seq
from bx import wiggle as bx_wig
from bx import bbi as bx_bbi
from bx import (
bbi as bx_bbi,
seq as bx_seq,
wiggle as bx_wig
)
from galaxy.util import sqlite
from . import (
base,
column,
external,
line
)
_TODO = """
use bx as much as possible
@@ -25,7 +30,6 @@ gff3 hierarchies
change SamtoolsDataProvider to use pysam
"""
import logging
log = logging.getLogger( __name__ )
@@ -150,7 +154,7 @@ class DatasetDataProvider( base.DataProvider ):
"""
region_column_names = ( 'chromCol', 'startCol', 'endCol' )
region_indices = [ self.get_metadata_column_index_by_name( name ) for name in region_column_names ]
if check and not all( map( lambda i: i is not None, region_indices) ):
if check and not all( _ is not None for _ in region_indices ):
raise ValueError( "Could not determine proper column indices for chrom, start, end: %s" % ( str( region_indices ) ) )
return region_indices
@@ -296,7 +300,7 @@ class GenomicRegionDataProvider( column.ColumnarDataProvider ):
if end_column is None:
end_column = dataset_source.get_metadata_column_index_by_name( 'endCol' )
indeces = [ chrom_column, start_column, end_column ]
if not all( map( lambda i: i is not None, indeces ) ):
if not all( _ is not None for _ in indeces ):
raise ValueError( "Could not determine proper column indeces for" +
" chrom, start, end: %s" % ( str( indeces ) ) )
kwargs.update({ 'indeces' : indeces })
@@ -14,11 +14,12 @@ DataProvider related decorators.
# adapted from: http://stackoverflow.com
# /questions/14095616/python-can-i-programmatically-decorate-class-methods-from-a-class-instance
from functools import wraps
import urllib2
import copy
import logging
from functools import wraps
from six.moves.urllib.parse import unquote
log = logging.getLogger( __name__ )
_DATAPROVIDER_CLASS_MAP_KEY = 'dataproviders'
@@ -65,7 +66,7 @@ def has_dataproviders( cls ):
# scan for methods with dataprovider names and add them to the map
# note: this has a 'cascading' effect
# where it's possible to override a super's provider with a sub's
for attr_key, attr_value in cls.__dict__.iteritems():
for attr_key, attr_value in cls.__dict__.items():
# can't use isinstance( attr_value, MethodType ) bc of wrapping
if( ( callable( attr_value ) ) and
( not attr_key.startswith( "__" ) ) and
@@ -129,7 +130,7 @@ def _parse_query_string_settings( query_kwargs, settings=None ):
'float' : float,
'bool' : bool,
'list:str' : lambda s: list_from_query_string( s ),
'list:escaped' : lambda s: [ urllib2.unquote( e ) for e in list_from_query_string( s ) ],
'list:escaped' : lambda s: [ unquote( e ) for e in list_from_query_string( s ) ],
'list:int' : lambda s: [ int( i ) for i in list_from_query_string( s ) ],
}
settings = settings or {}
+12 -9
View File
@@ -2,14 +2,18 @@
Data providers that iterate over a source that is not in memory
or not in a file.
"""
import base
import gzip
import line
import logging
import subprocess
import tempfile
import urllib
import urllib2
from six.moves.urllib.parse import urlencode
from six.moves.urllib.request import urlopen
from . import (
base,
line
)
_TODO = """
YAGNI: ftp, image, cryptos, sockets
@@ -17,7 +21,6 @@ job queue
admin: admin server log rgx/stats, ps aux
"""
import logging
log = logging.getLogger( __name__ )
@@ -105,13 +108,13 @@ class URLDataProvider( base.DataProvider ):
self.method = method
self.data = data or {}
encoded_data = urllib.urlencode( self.data )
encoded_data = urlencode( self.data )
if method == 'GET':
self.url += '?%s' % ( encoded_data )
opened = urllib2.urlopen( url )
opened = urlopen( url )
elif method == 'POST':
opened = urllib2.urlopen( url, encoded_data )
opened = urlopen( url, encoded_data )
else:
raise ValueError( 'Not a valid method: %s' % ( method ) )
@@ -1,14 +1,17 @@
"""
Dataproviders that iterate over lines from their sources.
"""
import logging
from xml.etree.ElementTree import (
Element,
iterparse
)
import line
from xml.etree.ElementTree import Element, iterparse
from . import line
_TODO = """
"""
import logging
log = logging.getLogger( __name__ )
+2 -2
View File
@@ -1,12 +1,12 @@
"""
Dataproviders that iterate over lines from their sources.
"""
import collections
import logging
import re
from . import base
import logging
log = logging.getLogger( __name__ )
_TODO = """
@@ -1,16 +1,24 @@
# Contains objects for using external display applications
import logging
import urllib
from six import string_types
from urllib import quote_plus
from copy import deepcopy
from galaxy.util import parse_xml, string_as_bool
from six import string_types
from six.moves.urllib.parse import quote_plus
from galaxy.util import (
parse_xml,
string_as_bool
)
from galaxy.util.odict import odict
from galaxy.util.template import fill_template
from galaxy.web import url_for
from parameters import DisplayApplicationParameter, DisplayApplicationDataParameter, DEFAULT_DATASET_NAME
from util import encode_dataset_user
from .parameters import (
DEFAULT_DATASET_NAME,
DisplayApplicationDataParameter,
DisplayApplicationParameter
)
from .util import encode_dataset_user
log = logging.getLogger( __name__ )
@@ -50,8 +58,8 @@ class DisplayApplicationLink( object ):
action="display_application",
dataset_id=dataset_hash,
user_id=user_hash,
app_name=urllib.quote_plus( self.display_application.id ),
link_name=urllib.quote_plus( self.id ),
app_name=quote_plus( self.display_application.id ),
link_name=quote_plus( self.id ),
app_action=None )
def get_inital_values( self, data, trans ):
@@ -60,7 +68,7 @@ class DisplayApplicationLink( object ):
else:
rval = odict()
rval.update( { 'BASE_URL': trans.request.base, 'APP': trans.app } ) # trans automatically appears as a response, need to add properties of trans that we want here
for key, value in BASE_PARAMS.iteritems(): # add helper functions/variables
for key, value in BASE_PARAMS.items(): # add helper functions/variables
rval[ key ] = value
rval[ DEFAULT_DATASET_NAME ] = data # always have the display dataset name available
return rval
@@ -70,7 +78,7 @@ class DisplayApplicationLink( object ):
other_values[ 'DATASET_HASH' ] = dataset_hash
other_values[ 'USER_HASH' ] = user_hash
ready = True
for name, param in self.parameters.iteritems():
for name, param in self.parameters.items():
assert name not in other_values, "The display parameter '%s' has been defined more than once." % name
if param.ready( other_values ):
if name in app_kwds and param.allow_override:
@@ -142,7 +150,7 @@ class DynamicDisplayApplicationBuilder( object ):
max_col = max( id_col, name_col )
dynamic_params = {}
if data_table is not None:
max_col = max( [ max_col ] + data_table.columns.values() )
max_col = max( [ max_col ] + list(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' ):
@@ -174,7 +182,7 @@ class DynamicDisplayApplicationBuilder( object ):
new_elem.set( 'id', fields[id_col] )
new_elem.set( 'name', fields[name_col] )
dynamic_values = {}
for key, attributes in dynamic_params.iteritems():
for key, attributes in dynamic_params.items():
value = fields[ attributes[ 'column' ] ]
if attributes['split']:
value = value.split( attributes['separator'] )
@@ -210,7 +218,7 @@ class PopulatedDisplayApplicationLink( object ):
def preparing_display( self ):
if not self.ready:
return self.link.parameters[ self.parameters.keys()[ -1 ] ].is_preparing( self.parameters )
return self.link.parameters[ list(self.parameters.keys())[-1] ].is_preparing( self.parameters )
return False
def prepare_display( self ):
@@ -218,8 +226,8 @@ class PopulatedDisplayApplicationLink( object ):
found_last = False
if not self.ready and not self.preparing_display():
other_values = self.parameters
for name, param in self.link.parameters.iteritems():
if found_last or other_values.keys()[ -1 ] == name: # found last parameter to be populated
for name, param in self.link.parameters.items():
if found_last or list(other_values.keys())[-1] == name: # found last parameter to be populated
found_last = True
value = param.prepare( other_values, self.dataset_hash, self.user_hash, self.trans )
rval.append( { 'name': name, 'value': value, 'param': param } )
@@ -231,7 +239,7 @@ class PopulatedDisplayApplicationLink( object ):
def get_prepare_steps( self, datasets_only=True ):
rval = []
for name, param in self.link.parameters.iteritems():
for name, param in self.link.parameters.items():
if datasets_only and not isinstance( param, DisplayApplicationDataParameter ):
continue
value = self.parameters.get( name, None )
@@ -243,7 +251,7 @@ class PopulatedDisplayApplicationLink( object ):
return fill_template( self.link.url.text, context=self.parameters )
def get_param_name_by_url( self, url ):
for name, parameter in self.link.parameters.iteritems():
for name, parameter in self.link.parameters.items():
if parameter.build_url( self.parameters ) == url:
return name
raise ValueError( "Unknown URL parameter name provided: %s" % url )
@@ -301,7 +309,7 @@ class DisplayApplication( object ):
def filter_by_dataset( self, data, trans ):
self._check_and_reload()
filtered = DisplayApplication( self.id, self.name, self.app, version=self.version )
for link_name, link_value in self.links.iteritems():
for link_name, link_value in self.links.items():
if link_value.filter_by_dataset( data, trans ):
filtered.links[link_name] = link_value
return filtered
@@ -318,13 +326,11 @@ class DisplayApplication( object ):
# We will not allow changing the id at this time (we'll need to fix several mappings upstream to handle this case)
assert attr_dict.get( 'id' ) == self.id, ValueError( "You cannot reload a Display application where the ID has changed. You will need to restart the server instead." )
# clear old links
for key in self.links.keys():
del self.links[key]
self.links = {}
# clear data table versions:
for key in self._data_table_versions.keys():
del self._data_table_versions[ key ]
self._data_table_versions = {}
# Set new attributes
for key, value in attr_dict.iteritems():
for key, value in attr_dict.items():
setattr( self, key, value )
# Load new links
self._load_links_from_elem( elem )
@@ -334,7 +340,7 @@ class DisplayApplication( object ):
self._data_table_versions[ table_name ] = version
def _requires_reload( self ):
for key, value in self._data_table_versions.iteritems():
for key, value in self._data_table_versions.items():
table = self.app.tool_data_tables.get( key, None )
if table and not table.is_current_version( value ):
return True
@@ -1,10 +1,12 @@
# Contains parameters that are used in Display Applications
import urllib
import mimetypes
from six.moves.urllib.parse import quote_plus
from galaxy.util import string_as_bool
from galaxy.util.bunch import Bunch
from galaxy.util.template import fill_template
from galaxy.web import url_for
import mimetypes
DEFAULT_DATASET_NAME = 'dataset'
@@ -110,7 +112,7 @@ class DisplayApplicationDataParameter( DisplayApplicationParameter ):
if target_ext and not converted_dataset:
if isinstance( data, DisplayDataValueWrapper ):
data = data.value
new_data = data.datatype.convert_dataset( trans, data, target_ext, return_output=True, visible=False ).values()[0]
new_data = next(iter(data.datatype.convert_dataset( trans, data, target_ext, return_output=True, visible=False ).values()))
new_data.hid = data.hid
new_data.name = data.name
trans.sa_session.add( new_data )
@@ -193,8 +195,8 @@ class DisplayParameterValueWrapper( object ):
action="display_application",
dataset_id=self._dataset_hash,
user_id=self._user_hash,
app_name=urllib.quote_plus( self.parameter.link.display_application.id ),
link_name=urllib.quote_plus( self.parameter.link.id ),
app_name=quote_plus( self.parameter.link.display_application.id ),
link_name=quote_plus( self.parameter.link.id ),
app_action=self.action_name,
action_param=self._url ) )
+8 -6
View File
@@ -1,15 +1,17 @@
"""
Graph content classes.
"""
import logging
import data
import tabular
import xml
import dataproviders
from galaxy.util import simplegraph
import logging
from . import (
data,
dataproviders,
tabular,
xml
)
log = logging.getLogger( __name__ )
-35
View File
@@ -7,7 +7,6 @@ import os
import sys
import tempfile
import numpy
from bx.intervals.io import GenomicIntervalReader, ParseError
from six.moves.urllib.parse import quote_plus
@@ -335,20 +334,6 @@ class Interval( Tabular ):
except:
return False
def get_track_window(self, dataset, data, start, end):
"""
Assumes the incoming track data is sorted already.
"""
window = list()
for record in data:
fields = record.rstrip("\n\r").split("\t")
record_chrom = fields[dataset.metadata.chromCol - 1]
record_start = int(fields[dataset.metadata.startCol - 1])
record_end = int(fields[dataset.metadata.endCol - 1])
if record_start < end and record_end > start:
window.append( (record_chrom, record_start, record_end) ) # Yes I did want to use a generator here, but it doesn't work downstream
return window
def get_track_resolution( self, dataset, start, end):
return None
@@ -1259,26 +1244,6 @@ class Wiggle( Tabular, _RemoteCallMixin ):
except:
return False
def get_track_window(self, dataset, data, start, end):
"""
Assumes we have a numpy file.
"""
range = end - start
# Determine appropriate resolution to plot ~1000 points
resolution = ( 10 ** math.ceil( math.log10( range / 1000 ) ) )
# Restrict to valid range
resolution = min( resolution, 100000 )
resolution = max( resolution, 1 )
# Memory map the array (don't load all the data)
data = numpy.load( data )
# Grab just what we need
t_start = math.floor( start / resolution )
t_end = math.ceil( end / resolution )
x = numpy.arange( t_start, t_end ) * resolution
y = data[ t_start : t_end ]
return list(zip(x.tolist(), y.tolist()))
def get_track_resolution( self, dataset, start, end):
range = end - start
# Determine appropriate resolution to plot ~1000 points
+10 -9
View File
@@ -1,17 +1,18 @@
# -*- coding: utf-8 -*-
from galaxy.datatypes import data
import logging
from galaxy.datatypes.sniff import get_headers
from galaxy.datatypes.data import get_file_peek
from galaxy.datatypes.tabular import Tabular
from galaxy.datatypes.binary import Binary
from galaxy.datatypes.xml import GenericXml
import subprocess
import os
import subprocess
from galaxy.datatypes import (
data,
metadata
)
from galaxy.datatypes.binary import Binary
from galaxy.datatypes.data import get_file_peek
from galaxy.datatypes.metadata import MetadataElement
from galaxy.datatypes import metadata
from galaxy.datatypes.sniff import get_headers
from galaxy.datatypes.tabular import Tabular
from galaxy.datatypes.xml import GenericXml
log = logging.getLogger(__name__)
+4 -3
View File
@@ -2,11 +2,12 @@
Mothur Metagenomics Datatypes
"""
import logging
import sys
import re
from galaxy.datatypes.sniff import get_headers
from galaxy.datatypes.metadata import MetadataElement
import sys
from galaxy.datatypes.data import Text
from galaxy.datatypes.metadata import MetadataElement
from galaxy.datatypes.sniff import get_headers
from galaxy.datatypes.tabular import Tabular
log = logging.getLogger(__name__)
+3 -3
View File
@@ -2,9 +2,9 @@
Neo4j Composite Dataset
"""
import logging
import sys
import shutil
import os
import shutil
import sys
from galaxy.datatypes.data import Data
from galaxy.datatypes.images import Html
@@ -29,7 +29,7 @@ class Neo4j(Html):
'<html><head><title>Files for Composite Dataset (%s)</title></head><p/>\
This composite dataset is composed of the following files:<p/><ul>' % (
self.file_ext)]
for composite_name, composite_file in self.get_composite_files(dataset=dataset).iteritems():
for composite_name, composite_file in self.get_composite_files(dataset=dataset).items():
opt_text = ''
if composite_file.optional:
opt_text = ' (optional)'
+62
View File
@@ -4,6 +4,8 @@ import re
from galaxy.datatypes.data import get_file_peek, Text
from galaxy.datatypes.metadata import MetadataElement, MetadataParameter
from galaxy.datatypes.sniff import get_headers
from galaxy.datatypes.tabular import Tabular
from galaxy.datatypes.text import Html
from galaxy.util import nice_size
@@ -89,6 +91,66 @@ class PlantTribes(Html):
log.warning("set_meta fname: %s %s" % (dataset.file_name if dataset and dataset.file_name else 'Unkwown', str(e)))
class PlantTribesKsComponents(Tabular):
file_ext = "ptkscmp"
MetadataElement(name="number_comp", default=0, desc="Number of significant components in the Ks distribution", readonly=True, visible=True, no_value=0)
def display_peek(self, dataset):
try:
return dataset.peek
except:
return "Significant components in the Ks distribution (%s)" % (nice_size(dataset.get_size()))
def set_meta(self, dataset, **kwd):
"""
Set the number of significant components in the Ks distribution.
The dataset will always be on the order of less than 10 lines.
"""
super(PlantTribesKsComponents, self).set_meta(dataset, **kwd)
significant_components = []
with open(dataset.file_name) as fh:
for i, line in enumerate(fh):
if i == 0:
# Skip the first line.
continue
line = line.strip()
items = line.split()
try:
# Could be \t.
significant_components.append(int(items[2]))
except Exception:
continue
if len(significant_components) > 0:
dataset.metadata.number_comp = max(significant_components)
def set_peek(self, dataset, is_multi_byte=False):
if not dataset.dataset.purged:
dataset.peek = get_file_peek(dataset.file_name, is_multi_byte=is_multi_byte)
if (dataset.metadata.number_comp == 1):
dataset.blurb = "1 significant component"
else:
dataset.blurb = "%s significant components" % dataset.metadata.number_comp
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
def sniff(self, filename):
"""
>>> from galaxy.datatypes.sniff import get_test_fname
>>> fname = get_test_fname('test_tab.bed')
>>> PlantTribesKsComponents().sniff(fname)
False
>>> fname = get_test_fname('1.ptkscmp')
>>> PlantTribesKsComponents().sniff(fname)
True
"""
try:
line_item_str = get_headers(filename, '\\t', 1)[0][0]
return line_item_str == 'species\tn\tnumber_comp\tlnL\tAIC\tBIC\tmean\tvariance\tporportion'
except Exception:
return False
class PlantTribesOrtho(PlantTribes):
"""
PlantTribes sequences classified into precomputed, orthologous gene family
+3 -2
View File
@@ -1,9 +1,10 @@
"""
Qualityscore class
"""
import data
import logging
from . import data
log = logging.getLogger(__name__)
+11 -17
View File
@@ -143,13 +143,10 @@ class Sequence( data.Text ):
if input_datasets[0].metadata is not None and input_datasets[0].metadata.sequences is not None:
total_sequences = input_datasets[0].metadata.sequences
else:
in_file = compression_utils.get_fileobj(input_datasets[0].file_name)
try:
with compression_utils.get_fileobj(input_datasets[0].file_name) as in_file:
total_sequences = long(0)
for i, line in enumerate(in_file):
total_sequences += 1
finally:
in_file.close()
total_sequences /= 4
sequences_per_file = cls.get_sequences_per_file(total_sequences, split_params)
@@ -570,8 +567,7 @@ class BaseFastq ( Sequence ):
data_lines = 0
sequences = 0
seq_counter = 0 # blocks should be 4 lines long
in_file = compression_utils.get_fileobj(dataset.file_name)
try:
with compression_utils.get_fileobj(dataset.file_name) as in_file:
for line in in_file:
line = line.strip()
if line and line.startswith( '#' ) and not data_lines:
@@ -590,8 +586,6 @@ class BaseFastq ( Sequence ):
sequences += 1
dataset.metadata.data_lines = data_lines
dataset.metadata.sequences = sequences
finally:
in_file.close()
def sniff( self, filename ):
"""
@@ -638,15 +632,15 @@ class BaseFastq ( Sequence ):
def display_data(self, trans, dataset, preview=False, filename=None, to_ext=None, **kwd):
if preview:
fh = compression_utils.get_fileobj(dataset.file_name)
max_peek_size = 1000000 # 1 MB
if os.stat( dataset.file_name ).st_size < max_peek_size:
mime = "text/plain"
self._clean_and_set_mime_type( trans, mime )
return fh.read()
return trans.stream_template_mako( "/dataset/large_file.mako",
truncated_data=fh.read(max_peek_size),
data=dataset)
with compression_utils.get_fileobj(dataset.file_name) as fh:
max_peek_size = 1000000 # 1 MB
if os.stat( dataset.file_name ).st_size < max_peek_size:
mime = "text/plain"
self._clean_and_set_mime_type( trans, mime )
return fh.read()
return trans.stream_template_mako( "/dataset/large_file.mako",
truncated_data=fh.read(max_peek_size),
data=dataset)
else:
return Sequence.display_data(self, trans, dataset, preview, filename, to_ext, **kwd)
+8 -9
View File
@@ -3,8 +3,9 @@ File format detector
"""
from __future__ import absolute_import
import gzip
import bz2
import codecs
import gzip
import logging
import os
import re
@@ -13,13 +14,13 @@ import sys
import tempfile
import zipfile
from encodings import search_function as encodings_search_function
from six import text_type
from galaxy import util
from galaxy.util import multi_byte
from galaxy.datatypes.binary import Binary
from galaxy.util import (
compression_utils,
multi_byte,
unicodify
)
from galaxy.util.checkers import (
@@ -28,7 +29,6 @@ from galaxy.util.checkers import (
is_bz2,
is_gzip
)
from galaxy.datatypes.binary import Binary
log = logging.getLogger(__name__)
@@ -48,7 +48,9 @@ def stream_to_open_named_file( stream, fd, filename, source_encoding=None, sourc
is_compressed = False
is_binary = False
is_multi_byte = False
if not target_encoding or not encodings_search_function( target_encoding ):
try:
codecs.lookup(target_encoding)
except:
target_encoding = util.DEFAULT_ENCODING # utf-8
if not source_encoding:
source_encoding = util.DEFAULT_ENCODING # sys.getdefaultencoding() would mimic old behavior (defaults to ascii)
@@ -211,8 +213,7 @@ def get_headers( fname, sep, count=60, is_multi_byte=False, comment_designator=N
[[''], ['chr7', 'bed2gff', 'AR', '26731313', '26731437', '.', '+', '.', 'score'], ['chr7', 'bed2gff', 'AR', '26731491', '26731536', '.', '+', '.', 'score'], ['chr7', 'bed2gff', 'AR', '26731541', '26731649', '.', '+', '.', 'score'], ['chr7', 'bed2gff', 'AR', '26731659', '26731841', '.', '+', '.', 'score']]
"""
headers = []
in_file = compression_utils.get_fileobj(fname)
try:
with compression_utils.get_fileobj(fname) as in_file:
idx = 0
for line in in_file:
line = line.rstrip('\n\r')
@@ -228,8 +229,6 @@ def get_headers( fname, sep, count=60, is_multi_byte=False, comment_designator=N
idx += 1
if idx == count:
break
finally:
in_file.close()
return headers
+11 -23
View File
@@ -787,8 +787,7 @@ class Eland( Tabular ):
- LANE, TILEm X, Y, INDEX, READ_NO, SEQ, QUAL, POSITION, *STRAND, FILT must be correct
- We will only check that up to the first 5 alignments are correctly formatted.
"""
try:
fh = compression_utils.get_fileobj(filename, gzip_only=True)
with compression_utils.get_fileobj(filename, gzip_only=True) as fh:
count = 0
while True:
line = fh.readline()
@@ -799,34 +798,25 @@ class Eland( Tabular ):
line_pieces = line.split('\t')
if len(line_pieces) != 22:
return False
try:
if long(line_pieces[1]) < 0:
raise Exception('Out of range')
if long(line_pieces[2]) < 0:
raise Exception('Out of range')
if long(line_pieces[3]) < 0:
raise Exception('Out of range')
int(line_pieces[4])
int(line_pieces[5])
# can get a lot more specific
except ValueError:
fh.close()
return False
if long(line_pieces[1]) < 0:
raise Exception('Out of range')
if long(line_pieces[2]) < 0:
raise Exception('Out of range')
if long(line_pieces[3]) < 0:
raise Exception('Out of range')
int(line_pieces[4])
int(line_pieces[5])
# can get a lot more specific
count += 1
if count == 5:
break
if count > 0:
fh.close()
return True
except:
pass
fh.close()
return False
def set_meta( self, dataset, overwrite=True, skip=None, max_data_lines=5, **kwd ):
if dataset.has_data():
dataset_fh = compression_utils.get_fileobj(dataset.file_name, gzip_only=True)
try:
with compression_utils.get_fileobj(dataset.file_name, gzip_only=True) as dataset_fh:
lanes = {}
tiles = {}
barcodes = {}
@@ -848,8 +838,6 @@ class Eland( Tabular ):
reads[line_pieces[7]] = 1
pass
dataset.metadata.data_lines = i + 1
finally:
dataset_fh.close()
dataset.metadata.comment_lines = 0
dataset.metadata.columns = 21
dataset.metadata.column_types = ['str', 'int', 'int', 'int', 'int', 'int', 'str', 'int', 'str', 'str', 'str', 'str', 'str', 'str', 'str', 'str', 'str', 'str', 'str', 'str', 'str']
+11
View File
@@ -0,0 +1,11 @@
species n number_comp lnL AIC BIC mean variance porportion
species1 1184 1 -1527.4110 3058.82 3068.98 0.4656 0.1675 1.00
species1 1184 2 -1490.7280 2991.46 3016.84 0.1718 0.0035 0.22
0.6173 0.2275 0.78
species1 1184 3 -1471.6980 2959.40 3000.01 0.6921 0.1806 0.65
5.9251 3.0703 0.02
0.1887 0.0054 0.33
species1 1184 4 -1443.1050 2908.21 2964.05 0.1219 0.0002 0.10
0.2589 0.0093 0.38
0.7900 0.1030 0.42
1.5944 1.7482 0.10
+8 -5
View File
@@ -1,12 +1,15 @@
"""
Triple format classes
"""
import re
import data
import logging
import xml
import text
import binary
import re
from . import (
binary,
data,
text,
xml
)
log = logging.getLogger(__name__)
+8 -10
View File
@@ -6,6 +6,8 @@ import copy
from bx.intervals.io import GenomicInterval, GenomicIntervalReader, MissingFieldError, NiceReaderWrapper, ParseError
from bx.tabular.io import Comment, Header
from six import Iterator
from galaxy.util.odict import odict
@@ -117,7 +119,7 @@ class GFFIntervalToBEDReaderWrapper( NiceReaderWrapper ):
return interval
class GFFReaderWrapper( NiceReaderWrapper ):
class GFFReaderWrapper( Iterator, NiceReaderWrapper ): # Iterator can be removed after bx-python library is ported to Python3
"""
Reader wrapper for GFF files.
@@ -149,15 +151,14 @@ class GFFReaderWrapper( NiceReaderWrapper ):
self.default_strand, fix_strand=self.fix_strand )
return interval
# For Python3 this needs to be changed to __next__() after bx-python library is ported too
def next( self ):
def __next__( self ):
""" Returns next GFFFeature. """
#
# Helper function.
#
def handle_parse_error( parse_error ):
def handle_parse_error( e ):
""" Actions to take when ParseError found. """
if self.outstream:
if self.print_delegate and hasattr(self.print_delegate, "__call__"):
@@ -434,19 +435,16 @@ def read_unordered_gtf( iterator, strict=False ):
chroms_features = {}
for count, intervals in enumerate( feature_intervals.values() ):
# Sort intervals by start position.
intervals.sort( lambda a, b: cmp( a.start, b.start ) )
intervals.sort(key=lambda _: _.start)
feature = GFFFeature( None, intervals=intervals )
if feature.chrom not in chroms_features:
chroms_features[ feature.chrom ] = []
chroms_features[ feature.chrom ].append( feature )
# Sort features by chrom, start position.
chroms_features_sorted = []
for chrom_features in chroms_features.values():
chroms_features_sorted.append( chrom_features )
chroms_features_sorted.sort( lambda a, b: cmp( a[0].chrom, b[0].chrom ) )
chroms_features_sorted = sorted(chroms_features.values(), key=lambda _: _[0].chrom)
for features in chroms_features_sorted:
features.sort( lambda a, b: cmp( a.start, b.start ) )
features.sort(key=lambda _: _.start)
# Yield comments first, then features.
# FIXME: comments can appear anywhere in file, not just the beginning.
+6 -3
View File
@@ -1,10 +1,13 @@
"""
XML format classes
"""
import re
import data
import logging
import dataproviders
import re
from . import (
data,
dataproviders
)
log = logging.getLogger(__name__)
+2 -2
View File
@@ -1,11 +1,11 @@
"""
Determine what optional dependencies are needed.
"""
import pkg_resources
from os.path import dirname, join
from xml.etree import ElementTree
import pkg_resources
from galaxy.util import asbool
from galaxy.util.properties import load_app_properties
@@ -23,7 +23,7 @@ bx-python
MarkupSafe
PyYAML
SQLAlchemy
mercurial
mercurial!=4.1.1 #conda's mercurial 4.1.1. is broken
pycrypto
# Install python_lzo if you want to support indexed access to lzo-compressed
+1 -1
View File
@@ -1216,7 +1216,7 @@ class JobWrapper( object, HasResourceParameters ):
# need to update all associated output hdas, i.e. history was shared with job running
for dataset in dataset_assoc.dataset.dataset.history_associations + dataset_assoc.dataset.dataset.library_associations:
purged = dataset.dataset.purged
if not purged:
if not purged and dataset.dataset.external_filename is None:
trynum = 0
while trynum < self.app.config.retry_job_output_collection:
try:
+2 -2
View File
@@ -152,9 +152,9 @@ class User( object, Dictifiable ):
histories, credentials, and roles.
"""
# attributes that will be accessed and returned when calling to_dict( view='collection' )
dict_collection_visible_keys = ( 'id', 'email', 'username' )
dict_collection_visible_keys = ( 'id', 'email', 'username', 'deleted', 'active', 'last_password_change' )
# attributes that will be accessed and returned when calling to_dict( view='element' )
dict_element_visible_keys = ( 'id', 'email', 'username', 'total_disk_usage', 'nice_total_disk_usage' )
dict_element_visible_keys = ( 'id', 'email', 'username', 'total_disk_usage', 'nice_total_disk_usage', 'deleted', 'active', 'last_password_change' )
def __init__( self, email=None, password=None ):
self.email = email
+9 -2
View File
@@ -2,10 +2,17 @@
Shared model and mapping code between Galaxy and Tool Shed, trying to
generalize to generic database connections.
"""
from inspect import (
getmembers,
isclass
)
from sqlalchemy.orm import (
scoped_session,
sessionmaker
)
from sqlalchemy.orm import scoped_session, sessionmaker
from galaxy.util.bunch import Bunch
from inspect import getmembers, isclass
# TODO: Refactor this to be a proper class, not a bunch.
+11 -6
View File
@@ -3,17 +3,21 @@ import copy
import json
import logging
import uuid
from sys import getsizeof
from itertools import chain
from collections import deque
from itertools import chain
from sys import getsizeof
import sqlalchemy
from sqlalchemy.ext.mutable import Mutable
from sqlalchemy.types import (
CHAR,
LargeBinary,
String,
TypeDecorator
)
from galaxy import app
from galaxy.util.aliaspickler import AliasPickleModule
from sqlalchemy.types import CHAR, LargeBinary, String, TypeDecorator
from sqlalchemy.ext.mutable import Mutable
log = logging.getLogger( __name__ )
@@ -234,6 +238,7 @@ def total_size(o, handlers={}, verbose=False):
"""
def dict_handler(d):
return chain.from_iterable(d.items())
all_handlers = { tuple: iter,
list: iter,
deque: iter,
@@ -268,7 +273,7 @@ class MetadataType( JSONType ):
def process_bind_param(self, value, dialect):
if value is not None:
if app.app and app.app.config.max_metadata_value_size:
for k, v in value.items():
for k, v in list(value.items()):
sz = total_size(v)
if sz > app.app.config.max_metadata_value_size:
del value[k]
+22 -6
View File
@@ -32,12 +32,28 @@ import parsley
from sqlalchemy import and_
from sqlalchemy.orm import aliased
from galaxy.model import (HistoryDatasetAssociation, LibraryDatasetDatasetAssociation,
History, Library, LibraryFolder, LibraryDataset, StoredWorkflowTagAssociation,
StoredWorkflow, HistoryTagAssociation, HistoryDatasetAssociationTagAssociation,
ExtendedMetadata, ExtendedMetadataIndex, HistoryAnnotationAssociation, Job, JobParameter,
JobToInputLibraryDatasetAssociation, JobToInputDatasetAssociation, JobToOutputDatasetAssociation,
Page, PageRevision)
from galaxy.model import (
ExtendedMetadata,
ExtendedMetadataIndex,
History,
HistoryAnnotationAssociation,
HistoryDatasetAssociation,
HistoryDatasetAssociationTagAssociation,
HistoryTagAssociation,
Job,
JobParameter,
JobToInputDatasetAssociation,
JobToInputLibraryDatasetAssociation,
JobToOutputDatasetAssociation,
Library,
LibraryDataset,
LibraryDatasetDatasetAssociation,
LibraryFolder,
Page,
PageRevision,
StoredWorkflow,
StoredWorkflowTagAssociation
)
from galaxy.model.tool_shed_install import ToolVersion
log = logging.getLogger( __name__ )
+5 -50
View File
@@ -1,10 +1,12 @@
import logging
import os
from galaxy.util.dictifiable import Dictifiable
from galaxy.util.bunch import Bunch
from six.moves.urllib.parse import urljoin
from galaxy.util import asbool
from galaxy.util.bunch import Bunch
from galaxy.util.dictifiable import Dictifiable
from tool_shed.util import common_util
from urlparse import urljoin
log = logging.getLogger( __name__ )
@@ -589,53 +591,6 @@ class ToolVersion( object, Dictifiable ):
self.tool_id = tool_id
self.tool_shed_repository = tool_shed_repository
def get_previous_version( self, app ):
parent_id = app.tool_version_cache.tool_id_to_parent_id.get(self.id, None)
if parent_id:
return app.tool_version_cache.tool_version_by_id[parent_id]
else:
return None
def get_next_version( self, app ):
child_id = app.tool_version_cache.parent_id_to_tool_id.get(self.id, None)
if child_id:
return app.tool_version_cache.tool_version_by_id[child_id]
else:
return None
def get_versions( self, app ):
tool_versions = []
# Prepend ancestors.
def __ancestors( app, tool_version ):
# Should we handle multiple parents at each level?
previous_version = tool_version.get_previous_version( app )
if previous_version:
if previous_version not in tool_versions:
tool_versions.insert( 0, previous_version )
__ancestors( app, previous_version )
# Append descendants.
def __descendants( app, tool_version ):
# Should we handle multiple child siblings at each level?
next_version = tool_version.get_next_version( app )
if next_version:
if next_version not in tool_versions:
tool_versions.append( next_version )
__descendants( app, next_version )
__ancestors( app, self )
if self not in tool_versions:
tool_versions.append( self )
__descendants( app, self )
return tool_versions
def get_version_ids( self, app, reverse=False ):
version_ids = [ tool_version.tool_id for tool_version in self.get_versions( app ) ]
if reverse:
version_ids.reverse()
return version_ids
def to_dict( self, view='element' ):
rval = super( ToolVersion, self ).to_dict( view=view )
rval[ 'tool_name' ] = self.tool_id
+21 -5
View File
@@ -1,11 +1,27 @@
from sqlalchemy import (
Boolean,
Column,
DateTime,
ForeignKey,
Integer,
MetaData,
String,
Table,
TEXT
)
from sqlalchemy.orm import (
mapper,
relation
)
from galaxy.model import tool_shed_install as install_model
from sqlalchemy import MetaData
from sqlalchemy import Boolean, Column, DateTime, ForeignKey, Integer, String, Table, TEXT
from sqlalchemy.orm import relation, mapper
from galaxy.model.custom_types import JSONType, TrimmedString
from galaxy.model.orm.now import now
from galaxy.model.base import ModelMapping
from galaxy.model.custom_types import (
JSONType,
TrimmedString
)
from galaxy.model.orm.engine_factory import build_engine
from galaxy.model.orm.now import now
metadata = MetaData()
@@ -1,14 +1,17 @@
import sys
import os.path
import logging
import os.path
import sys
# from sqlalchemy import *
from sqlalchemy import create_engine
from sqlalchemy import MetaData
from sqlalchemy import Table
from migrate.versioning import (
repository,
schema
)
from sqlalchemy import (
create_engine,
MetaData,
Table
)
from sqlalchemy.exc import NoSuchTableError
from migrate.versioning import repository, schema
log = logging.getLogger( __name__ )
-4
View File
@@ -102,10 +102,8 @@ def _get_new_toolbox(app):
"""
from galaxy import tools
from galaxy.tools.special_tools import load_lib_tools
from galaxy.tools.toolbox.lineages.tool_shed import ToolVersionCache
if hasattr(app, 'tool_shed_repository_cache'):
app.tool_shed_repository_cache.rebuild()
app.tool_version_cache = ToolVersionCache(app) # Load new tools into version cache
tool_configs = app.config.tool_configs
if app.config.migrated_tools_config not in tool_configs:
tool_configs.append(app.config.migrated_tools_config)
@@ -122,7 +120,6 @@ def _get_new_toolbox(app):
def reload_data_managers(app, **kwargs):
reload_timer = util.ExecutionTimer()
from galaxy.tools.data_manager.manager import DataManagers
from galaxy.tools.toolbox.lineages.tool_shed import ToolVersionCache
log.debug("Executing data managers reload on '%s'", app.config.server_name)
if hasattr(app, 'tool_shed_repository_cache'):
app.tool_shed_repository_cache.rebuild()
@@ -131,7 +128,6 @@ def reload_data_managers(app, **kwargs):
reload_count = app.data_managers._reload_count
app.data_managers = DataManagers(app)
app.data_managers._reload_count = reload_count + 1
app.tool_version_cache = ToolVersionCache(app)
if hasattr(app, 'tool_cache'):
app.tool_cache.reset_status()
log.debug("Data managers reloaded %s", reload_timer)
+2 -2
View File
@@ -6,7 +6,7 @@ import logging
import socket
from datetime import datetime, timedelta
from sqlalchemy import and_, false, or_, not_
from sqlalchemy import and_, false, not_, or_
from sqlalchemy.orm import eagerload_all
from galaxy.util import listify
@@ -1008,7 +1008,7 @@ class GalaxyRBACAgent( RBACAgent ):
# Add the new permissions on library_item
for item_class, permission_class in self.library_item_assocs:
if isinstance( library_item, item_class ):
for action, roles in permissions.items():
for action, roles in list(permissions.items()):
if isinstance( action, Action ):
action = action.action
for role_assoc in [ permission_class( action, library_item, role ) for role in roles ]:
+7 -6
View File
@@ -1,10 +1,11 @@
import hmac
import hashlib
from struct import Struct
from operator import xor
from itertools import starmap
from os import urandom
import hmac
from base64 import b64encode
from itertools import starmap
from operator import xor
from os import urandom
from struct import Struct
from galaxy.util import safe_str_cmp
SALT_LENGTH = 12
@@ -77,6 +78,6 @@ def pbkdf2_bin( data, salt, iterations=1000, keylen=24, hashfunc=None ):
rv = u = _pseudorandom(salt + _pack_int(block))
for i in range(iterations - 1):
u = _pseudorandom(''.join(map(chr, u)))
rv = starmap( xor, zip( rv, u ) ) # Python < 2.6.8: starmap requires function inputs to be tuples, so we need to use zip instead of izip
rv = starmap( xor, zip( rv, u ) )
buf.extend(rv)
return ''.join(map(chr, buf))[:keylen]
+10 -15
View File
@@ -414,9 +414,8 @@ class Tool( object, Dictifiable ):
self.guid = guid
self.old_id = None
self.version = None
self._lineage = None
self.dependencies = []
# Enable easy access to this tool's version lineage.
self.lineage_ids = []
# populate toolshed repository info, if available
self.populate_tool_shed_info()
# add tool resource parameters
@@ -440,17 +439,17 @@ class Tool( object, Dictifiable ):
return self.app.model.context
@property
def tool_version( self ):
"""Return a ToolVersion if one exists for our id"""
return self.app.tool_version_cache.tool_version_by_tool_id.get(self.id)
def lineage(self):
"""Return ToolLineage for this tool."""
return self._lineage
@property
def tool_versions( self ):
# If we have versions, return them.
tool_version = self.tool_version
if tool_version:
return tool_version.get_versions( self.app )
return []
if self.lineage:
return self.lineage.get_versions()
else:
return []
@property
def tool_shed_repository( self ):
@@ -1795,7 +1794,7 @@ class Tool( object, Dictifiable ):
if job:
try:
job_params = job.get_param_values( self.app, ignore_errors=True )
tool_warnings = self.check_and_update_param_values( job_params, request_context, update_values=False )
tool_warnings = self.check_and_update_param_values( job_params, request_context, update_values=True )
self._map_source_to_history( request_context, self.inputs, job_params )
tool_message = self._compare_tool_version( job )
params_to_incoming( kwd, self.inputs, job_params, self.app )
@@ -1832,11 +1831,7 @@ class Tool( object, Dictifiable ):
tool_help = unicodify( tool_help, 'utf-8' )
# create tool versions
tool_versions = []
tools = self.app.toolbox.get_loaded_tools_by_lineage( self.id )
for t in tools:
if t.version not in tool_versions:
tool_versions.append( t.version )
tool_versions = self.lineage.tool_versions
# update tool model
tool_model.update({
+9 -24
View File
@@ -289,9 +289,7 @@ class AbstractToolBox( Dictifiable, ManagesIntegratedToolPanelMixin, object ):
inserted = True
if not inserted:
# Check the tool's installed versions.
versions = []
if hasattr(tool, 'lineage'):
versions = tool.lineage.get_versions()
versions = tool.lineage.get_versions()
for tool_lineage_version in versions:
lineage_id = tool_lineage_version.id
index = self._integrated_tool_panel.index_of_tool_id(lineage_id)
@@ -415,10 +413,11 @@ class AbstractToolBox( Dictifiable, ManagesIntegratedToolPanelMixin, object ):
tool_ids = [tool_id]
for tool_id in tool_ids:
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)
return self._tools_by_id[ tool_id ]
if not tool_version:
return self._tools_by_id[ tool_id ]
elif tool_version in self._tool_versions_by_id[ tool_id ]:
return self._tool_versions_by_id[ tool_id ][ tool_version ]
elif exact:
# We're looking for an exact match, so we skip lineage and
# versionless mapping, though we may want to check duplicate
@@ -427,8 +426,6 @@ class AbstractToolBox( Dictifiable, ManagesIntegratedToolPanelMixin, object ):
# 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 not tool_lineage:
tool_lineage = self._lineage_map.get_versionless( tool_id )
if tool_lineage:
lineage_tool_versions = tool_lineage.get_versions( )
for lineage_tool_version in lineage_tool_versions:
@@ -567,9 +564,8 @@ class AbstractToolBox( Dictifiable, ManagesIntegratedToolPanelMixin, object ):
tool.installed_changeset_revision = tool_shed_repository.installed_changeset_revision
tool.guid = guid
tool.version = item.elem.find( "version" ).text
# Make sure tools have a tool_version object.
tool_lineage = self._lineage_map.register( tool, from_toolshed=guid )
tool.lineage = tool_lineage
# Make sure tools are registered in self._lineage_map.
tool._lineage = self._lineage_map.register( tool )
if item.has_elem:
self._tool_tag_manager.handle_tags( tool.id, item.elem )
self.__add_tool( tool, load_panel_dict, panel_dict )
@@ -949,10 +945,8 @@ class AbstractToolBox( Dictifiable, ManagesIntegratedToolPanelMixin, object ):
"""
if tool_lineage is None:
assert tool is not None
if not hasattr( tool, "lineage" ):
return None
tool_lineage = tool.lineage
lineage_tool_versions = tool_lineage.get_versions( reverse=True )
lineage_tool_versions = reversed(tool_lineage.get_versions())
for lineage_tool_version in lineage_tool_versions:
lineage_tool = self._tool_from_lineage_version( lineage_tool_version )
if lineage_tool:
@@ -965,16 +959,7 @@ class AbstractToolBox( Dictifiable, ManagesIntegratedToolPanelMixin, object ):
""" Return True if tool1 is considered "newer" given its own lineage
description.
"""
if not hasattr( tool1, "lineage" ):
return True
lineage_tool_versions = tool1.lineage.get_versions()
for lineage_tool_version in lineage_tool_versions:
lineage_tool = self._tool_from_lineage_version( lineage_tool_version )
if lineage_tool is tool1:
return False
if lineage_tool is tool2:
return True
return True
return tool1.version_object > tool2.version_object
def _tool_from_lineage_version( self, lineage_tool_version ):
if lineage_tool_version.id_based:
@@ -1,6 +1,5 @@
from .factory import LineageMap
from .interface import ToolLineage
from .tool_shed import ToolVersionCache
__all__ = ("LineageMap", "ToolLineage", "ToolVersionCache")
__all__ = ("LineageMap", "ToolLineage")
+26 -20
View File
@@ -1,15 +1,6 @@
from .stock import StockLineage
from .tool_shed import ToolShedLineage
from galaxy.util.tool_version import remove_version_from_guid
def remove_version_from_guid( guid ):
"""
Removes version from toolshed-derived tool_id(=guid).
"""
if "/repos/" not in guid:
return None
last_slash = guid.rfind('/')
return guid[:last_slash]
from .interface import ToolLineage
class LineageMap(object):
@@ -20,13 +11,17 @@ class LineageMap(object):
self.lineage_map = {}
self.app = app
def register(self, tool, from_toolshed=False):
def register(self, tool):
tool_id = tool.id
versionless_tool_id = remove_version_from_guid( tool_id )
if from_toolshed:
lineage = ToolShedLineage.from_tool(self.app, tool)
versionless_tool_id = remove_version_from_guid(tool_id)
lineage = self.lineage_map.get(versionless_tool_id)
if not lineage:
lineage = ToolLineage.from_tool( tool )
else:
lineage = StockLineage.from_tool( tool )
# A lineage for a tool with the same versionless_tool_id exists,
# but this lineage may not have the current tools' version,
# so we add tool.version to the lineage
lineage.register_version(tool.version)
if versionless_tool_id and versionless_tool_id not in self.lineage_map:
self.lineage_map[versionless_tool_id] = lineage
if tool_id not in self.lineage_map:
@@ -34,14 +29,25 @@ class LineageMap(object):
return self.lineage_map[tool_id]
def get(self, tool_id):
"""
Get lineage for `tool_id`.
By preference the lineage for a version-agnostic tool_id is returned.
Falls back to fetching the lineage only when this fails.
This happens when the tool_id does not contain a version.
"""
lineage = self._get_versionless(tool_id)
if lineage:
return lineage
if tool_id not in self.lineage_map:
lineage = ToolShedLineage.from_tool_id( self.app, tool_id )
tool = self.app.toolbox._tools_by_id.get(tool_id)
if tool:
lineage = ToolLineage.from_tool( tool )
if lineage:
self.lineage_map[tool_id] = lineage
return self.lineage_map.get(tool_id)
return self.lineage_map.get(tool_id, None)
def get_versionless(self, tool_id):
def _get_versionless(self, tool_id):
versionless_tool_id = remove_version_from_guid(tool_id)
return self.lineage_map.get(versionless_tool_id, None)
+59 -25
View File
@@ -1,21 +1,8 @@
from abc import (
ABCMeta,
abstractmethod
)
import threading
import six
from distutils.version import LooseVersion
@six.add_metaclass(ABCMeta)
class ToolLineage(object):
"""
"""
@abstractmethod
def get_versions( self, reverse=False ):
""" Return an ordered list of lineages (ToolLineageVersion) in this
chain, from oldest to newest.
"""
from galaxy.util.tool_version import remove_version_from_guid
class ToolLineageVersion(object):
@@ -27,15 +14,6 @@ class ToolLineageVersion(object):
self.id = id
self.version = version
@staticmethod
def from_id_and_verion( id, version ):
assert version is not None
return ToolLineageVersion( id, version )
@staticmethod
def from_guid( guid ):
return ToolLineageVersion( guid, None )
@property
def id_based( self ):
""" Return True if the lineage is defined by GUIDs (in this
@@ -50,3 +28,59 @@ class ToolLineageVersion(object):
id=self.id,
version=self.version,
)
class ToolLineage:
""" Simple tool's loaded directly from file system with lineage
determined solely by distutil's LooseVersion naming scheme.
"""
lineages_by_id = {}
lock = threading.Lock()
def __init__(self, tool_id, **kwds):
self.tool_id = tool_id
self._tool_versions = set()
@property
def tool_versions(self):
return sorted(self._tool_versions, key=LooseVersion)
@property
def tool_ids(self):
versionless_tool_id = remove_version_from_guid(self.tool_id)
tool_id = versionless_tool_id or self.tool_id
return ["%s/%s" % (tool_id, version) for version in self.tool_versions]
@staticmethod
def from_tool( tool ):
tool_id = tool.id
lineages_by_id = ToolLineage.lineages_by_id
with ToolLineage.lock:
if tool_id not in lineages_by_id:
lineages_by_id[ tool_id ] = ToolLineage( tool_id )
lineage = lineages_by_id[ tool_id ]
lineage.register_version( tool.version )
return lineage
def register_version( self, tool_version ):
assert tool_version is not None
self._tool_versions.add( str(tool_version) )
def get_versions( self ):
"""
Return an ordered list of lineages (ToolLineageVersion) in this
chain, from oldest to newest.
"""
return [ ToolLineageVersion( tool_id, tool_version ) for tool_id, tool_version in zip(self.tool_ids, self.tool_versions) ]
def get_version_ids(self, reverse=False):
if reverse:
return list(reversed(self.tool_ids))
return self.tool_ids
def to_dict(self):
return dict(
tool_id=self.tool_id,
tool_versions=list(self.tool_versions),
lineage_type='stock',
)
@@ -1,51 +0,0 @@
import threading
from distutils.version import LooseVersion
from .interface import ToolLineage
from .interface import ToolLineageVersion
class StockLineage(ToolLineage):
""" Simple tool's loaded directly from file system with lineage
determined solely by distutil's LooseVersion naming scheme.
"""
lineages_by_id = {}
lock = threading.Lock()
def __init__(self, tool_id, **kwds):
self.tool_id = tool_id
self.tool_versions = set()
@staticmethod
def from_tool( tool ):
tool_id = tool.id
lineages_by_id = StockLineage.lineages_by_id
with StockLineage.lock:
if tool_id not in lineages_by_id:
lineages_by_id[ tool_id ] = StockLineage( tool_id )
lineage = lineages_by_id[ tool_id ]
lineage.register_version( tool.version )
return lineage
def register_version( self, tool_version ):
assert tool_version is not None
self.tool_versions.add( tool_version )
def get_versions( self, reverse=False ):
versions = [ ToolLineageVersion( self.tool_id, v ) for v in self.tool_versions ]
# Sort using LooseVersion which defines an appropriate __cmp__
# method for comparing tool versions.
return sorted( versions, key=_to_loose_version, reverse=reverse )
def to_dict(self):
return dict(
tool_id=self.tool_id,
tool_versions=list(self.tool_versions),
lineage_type='stock',
)
def _to_loose_version( tool_lineage_version ):
version = str( tool_lineage_version.version )
return LooseVersion( version )
@@ -1,98 +0,0 @@
from .interface import ToolLineage, ToolLineageVersion
try:
from galaxy.model.tool_shed_install import ToolVersion
except ImportError:
ToolVersion = None
class ToolVersionCache(object):
"""
Instances of this class allow looking up tool_version objects from memory
(instead of querying the database) using the tool_version id or the tool_id.
This is used to lookup parent tool_version ids using child tool_id, or the
inverse, and getting all previous/next tool versions without numerous
database requests.
"""
def __init__(self, app):
self.app = app
self.tool_version_by_id, self.tool_version_by_tool_id = self.get_tool_versions()
self.tool_id_to_parent_id, self.parent_id_to_tool_id = self.get_tva_map()
def get_tva_map(self):
"""
Retrieves all ToolVersionAssociation objects from the database, and builds
dictionaries that can be used to either get a tools' parent tool_version id
(which can be used to get the parent's tool_version object), or to get the
child's tool id using the parent's tool_version id.
"""
tvas = self.app.install_model.context.query(self.app.install_model.ToolVersionAssociation).all()
tool_id_to_parent_id = {tva.tool_id: tva.parent_id for tva in tvas}
parent_id_to_tool_id = {tva.parent_id: tva.tool_id for tva in tvas}
return tool_id_to_parent_id, parent_id_to_tool_id
def get_tool_versions(self):
"""
Get all tool_version objects from the database and build 2 dictionaries,
with tool_version id or tool_id as key and the tool_version object as value.
"""
tool_versions = self.app.install_model.context.query(self.app.install_model.ToolVersion).all()
tool_version_by_id = {tv.id: tv for tv in tool_versions}
tool_version_by_tool_id = {tv.tool_id: tv for tv in tool_versions}
return tool_version_by_id, tool_version_by_tool_id
class ToolShedLineage(ToolLineage):
""" Representation of tool lineage derived from tool shed repository
installations. """
def __init__(self, app, tool_version, tool_shed_repository=None):
if ToolVersion is None:
raise Exception("Tool shed models not present, can't create tool shed lineages.")
self.app = app
self.tool_version_id = tool_version.id
# Only used for logging
self._tool_shed_repository = tool_shed_repository
@staticmethod
def from_tool( app, tool ):
# Make sure the tool has a tool_version.
if not get_installed_tool_version( app, tool.id ):
tool_version = ToolVersion( tool_id=tool.id, tool_shed_repository=tool.tool_shed_repository )
app.install_model.context.add( tool_version )
app.install_model.context.flush()
app.tool_version_cache = ToolVersionCache(app)
return ToolShedLineage( app, tool.tool_version )
@staticmethod
def from_tool_id( app, tool_id ):
tool_version = get_installed_tool_version( app, tool_id )
if tool_version:
return ToolShedLineage( app, tool_version )
else:
return None
def get_version_ids( self, reverse=False ):
tool_version = self.app.install_model.context.query( ToolVersion ).get( self.tool_version_id )
result = tool_version.get_version_ids( self.app, reverse=reverse )
return result
def get_versions( self, reverse=False ):
return [ ToolLineageVersion.from_guid(_) for _ in self.get_version_ids( reverse=reverse ) ]
def to_dict(self):
tool_shed_repository = self._tool_shed_repository
rval = dict(
tool_version_id=self.tool_version_id,
tool_versions=[v.to_dict() for v in self.get_versions()],
tool_shed_repository=tool_shed_repository if tool_shed_repository is not None else None,
lineage_type='tool_shed',
)
return rval
def get_installed_tool_version( app, tool_id ):
return app.tool_version_cache.tool_version_by_tool_id.get(tool_id, None)
__all__ = ( "ToolShedLineage", )
+8
View File
@@ -0,0 +1,8 @@
def remove_version_from_guid(guid):
"""
Removes version from toolshed-derived tool_id(=guid).
"""
if "/" not in guid:
return None
last_slash = guid.rfind('/')
return guid[:last_slash]
+1 -1
View File
@@ -204,7 +204,7 @@ class JobController( BaseAPIController, UsesLibraryMixinItems ):
job = self.__get_job(trans, id)
if not job:
raise exceptions.ObjectNotFound("Could not access job with id '%s'" % id)
tool = self.app.toolbox.get_tool( job.tool_id, job.tool_version )
tool = self.app.toolbox.get_tool( job.tool_id, kwd.get('tool_version') or job.tool_version )
if tool is None:
raise exceptions.ObjectNotFound( "Requested tool not found" )
if not tool.is_workflow_compatible:
@@ -404,19 +404,19 @@ class LibraryDatasetsController( BaseAPIController, UsesVisualizationMixin ):
"""
if payload:
kwd.update(payload)
kwd['space_to_tab'] = False
kwd['to_posix_lines'] = True
kwd[ 'space_to_tab' ] = False
kwd[ 'to_posix_lines' ] = True
kwd[ 'dbkey' ] = kwd.get( 'dbkey', '?' )
kwd[ 'file_type' ] = kwd.get( 'file_type', 'auto' )
kwd['link_data_only'] = 'link_to_files' if util.string_as_bool( kwd.get( 'link_data', False ) ) else 'copy_files'
kwd[ 'link_data_only' ] = 'link_to_files' if util.asbool( kwd.get( 'link_data', False ) ) else 'copy_files'
encoded_folder_id = kwd.get( 'encoded_folder_id', None )
if encoded_folder_id is not None:
folder_id = self.folder_manager.cut_and_decode( trans, encoded_folder_id )
else:
raise exceptions.RequestParameterMissingException( 'The required atribute encoded_folder_id is missing.' )
raise exceptions.RequestParameterMissingException( 'The required attribute encoded_folder_id is missing.' )
path = kwd.get( 'path', None)
if path is None:
raise exceptions.RequestParameterMissingException( 'The required atribute path is missing.' )
raise exceptions.RequestParameterMissingException( 'The required attribute path is missing.' )
folder = self.folder_manager.get( trans, folder_id )
source = kwd.get( 'source', None )
@@ -15,6 +15,7 @@ from galaxy.web import _future_expose_api as expose_api
from galaxy.web.base.controller import BaseAPIController
from tool_shed.galaxy_install.install_manager import InstallRepositoryManager
from tool_shed.galaxy_install.installed_repository_manager import InstalledRepositoryManager
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.repair_repository_manager import RepairRepositoryManager
from tool_shed.util import common_util
@@ -616,6 +617,46 @@ class ToolShedRepositoriesController( BaseAPIController ):
all_installed_tool_shed_repositories.extend( installed_tool_shed_repositories )
return all_installed_tool_shed_repositories
@expose_api
def uninstall_repository(self, trans, id=None, **kwd):
"""
DELETE /api/tool_shed_repositories/id
DELETE /api/tool_shed_repositories/
:param id: encoded repository id. Either id or name, owner, changeset_revision and tool_shed_url need to be supplied
:param kwd: 'remove_from_disk' : Remove repository from disk or deactivate repository.
Defaults to `True` (= remove repository from disk).
'name' : Repository name
'owner' : Repository owner
'changeset_revision': Changeset revision to uninstall
'tool_shed_url' : Tool Shed URL
"""
if id:
try:
repository = repository_util.get_tool_shed_repository_by_id(self.app, id)
except ValueError:
raise HTTPBadRequest(detail="No repository with id '%s' found" % id)
else:
tsr_arguments = ['name', 'owner', 'changeset_revision', 'tool_shed_url']
try:
tsr_arguments = {key: kwd[key] for key in tsr_arguments}
except KeyError as e:
raise HTTPBadRequest(detail="Missing required parameter '%s'" % e.args[0])
repository = repository_util.get_installed_repository(app=self.app,
tool_shed=tsr_arguments['tool_shed_url'],
name=tsr_arguments['name'],
owner=tsr_arguments['owner'],
changeset_revision=tsr_arguments['changeset_revision'])
if not repository:
raise HTTPBadRequest(detail="Repository not found")
irm = InstalledRepositoryManager(app=self.app)
errors = irm.uninstall_repository(repository=repository, remove_from_disk=kwd.get('remove_from_disk', True))
if not errors:
action = 'removed' if kwd.get('remove_from_disk', True) else 'deactivated'
return {'message': 'The repository named %s has been %s.' % (repository.name, action)}
else:
raise Exception('Attempting to uninstall tool dependencies for repository named %s resulted in errors: %s' % (repository.name, errors))
@expose_api
def repair_repository_revision( self, trans, payload, **kwd ):
"""
+12 -4
View File
@@ -113,10 +113,18 @@ class UserAPIController( BaseAPIController, UsesTagsMixin, CreatesUsersMixin, Cr
item = user.to_dict( value_mapper={ 'id': trans.security.encode_id } )
# If NOT configured to expose_email, do not expose email UNLESS the user is self, or
# the user is an admin
if not trans.app.config.expose_user_name and user is not trans.user and not trans.user_is_admin():
del item['username']
if not trans.app.config.expose_user_email and user is not trans.user and not trans.user_is_admin():
del item['email']
if user is not trans.user and not trans.user_is_admin():
expose_keys = ["id"]
if trans.app.config.expose_user_name:
expose_keys.append("username")
if trans.app.config.expose_user_email:
expose_keys.append("email")
new_item = {}
for key, value in item.items():
if key in expose_keys:
new_item[key] = value
item = new_item
# TODO: move into api_values
rval.append( item )
return rval
+19
View File
@@ -113,6 +113,7 @@ def paste_app_factory( global_conf, **kwargs ):
webapp.add_client_route( '/pages/list' )
webapp.add_client_route( '/pages/list_published' )
webapp.add_client_route( '/histories/list' )
webapp.add_client_route( '/histories/list_shared' )
webapp.add_client_route( '/datasets/list' )
webapp.add_client_route( '/workflow/run' )
webapp.add_client_route( '/workflow/import_workflow' )
@@ -826,12 +827,30 @@ def populate_api_routes( webapp, app ):
action='status',
conditions=dict( method=[ "GET" ] ) )
webapp.mapper.connect( 'install_repository',
'/api/tool_shed_repositories',
controller='tool_shed_repositories',
action='install_repository_revision',
conditions=dict( method=[ 'POST' ] ) )
webapp.mapper.connect( 'install_repository',
'/api/tool_shed_repositories/install',
controller='tool_shed_repositories',
action='install',
conditions=dict( method=[ 'POST' ] ) )
webapp.mapper.connect( 'tool_shed_repository',
'/api/tool_shed_repositories',
controller='tool_shed_repositories',
action='uninstall_repository',
conditions=dict( method=[ "DELETE" ]))
webapp.mapper.connect( 'tool_shed_repository',
'/api/tool_shed_repositories/{id}',
controller='tool_shed_repositories',
action='uninstall_repository',
conditions=dict( method=[ "DELETE" ]))
# Galaxy API for tool shed features.
webapp.mapper.resource( 'tool_shed_repository',
'tool_shed_repositories',
+11 -7
View File
@@ -455,13 +455,17 @@ class ToolVersionListGrid( grids.Grid ):
def get_value( self, trans, grid, tool_version ):
tool_ids_str = ''
toolbox = trans.app.toolbox
for tool_id in tool_version.get_version_ids( trans.app ):
if toolbox.has_tool( tool_id, exact=True ):
link = url_for( controller='tool_runner', tool_id=tool_id )
link_str = '<a target="_blank" href="%s">' % link
tool_ids_str += '<div class="count-box state-color-ok">%s%s</a></div><br/>' % ( link_str, tool_id )
else:
tool_ids_str += '%s<br/>' % tool_id
tool = toolbox._tools_by_id.get(tool_version.tool_id)
if tool:
for tool_id in tool.lineage.tool_ids:
if toolbox.has_tool( tool_id, exact=True ):
link = url_for( controller='tool_runner', tool_id=tool_id )
link_str = '<a target="_blank" href="%s">' % link
tool_ids_str += '<div class="count-box state-color-ok">%s%s</a></div><br/>' % ( link_str, tool_id )
else:
tool_ids_str += '%s<br/>' % tool_version.tool_id
else:
tool_ids_str += '%s<br/>' % tool_version.tool_id
return tool_ids_str
# Grid definition
@@ -1,7 +1,6 @@
import json
import logging
import os
import shutil
from admin import AdminGalaxy
from six import string_types
@@ -13,8 +12,8 @@ from galaxy.tools.deps import views
from galaxy.web.form_builder import CheckboxField
from tool_shed.galaxy_install import dependency_display
from tool_shed.galaxy_install import install_manager
from tool_shed.galaxy_install.datatypes import custom_datatype_manager
from tool_shed.galaxy_install.grids import admin_toolshed_grids
from tool_shed.galaxy_install.installed_repository_manager import InstalledRepositoryManager
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.repair_repository_manager import RepairRepositoryManager
from tool_shed.galaxy_install.repository_dependencies import repository_dependency_manager
@@ -249,84 +248,17 @@ class AdminToolshed( AdminGalaxy ):
tool_shed_repositories = repository_util.get_installed_tool_shed_repository( trans.app, kwd[ 'id' ] )
if not isinstance( tool_shed_repositories, list ):
tool_shed_repositories = [tool_shed_repositories]
irm = InstalledRepositoryManager(app=trans.app)
for tool_shed_repository in tool_shed_repositories:
shed_tool_conf, tool_path, relative_install_dir = \
suc.get_tool_panel_config_tool_path_install_dir( trans.app, tool_shed_repository )
if relative_install_dir:
if tool_path:
relative_install_dir = os.path.join( tool_path, relative_install_dir )
repository_install_dir = os.path.abspath( relative_install_dir )
else:
repository_install_dir = None
errors = ''
if kwd.get( 'deactivate_or_uninstall_repository_button', False ):
if tool_shed_repository.includes_tools_for_display_in_tool_panel:
# Handle tool panel alterations.
tpm = tool_panel_manager.ToolPanelManager( trans.app )
tpm.remove_repository_contents( tool_shed_repository,
shed_tool_conf,
uninstall=remove_from_disk_checked )
if tool_shed_repository.includes_data_managers:
dmh = data_manager.DataManagerHandler( trans.app )
dmh.remove_from_data_manager( tool_shed_repository )
if tool_shed_repository.includes_datatypes:
# Deactivate proprietary datatypes.
cdl = custom_datatype_manager.CustomDatatypeLoader( trans.app )
installed_repository_dict = cdl.load_installed_datatypes( tool_shed_repository,
repository_install_dir,
deactivate=True )
if installed_repository_dict:
converter_path = installed_repository_dict.get( 'converter_path' )
if converter_path is not None:
cdl.load_installed_datatype_converters( installed_repository_dict, deactivate=True )
display_path = installed_repository_dict.get( 'display_path' )
if display_path is not None:
cdl.load_installed_display_applications( installed_repository_dict, deactivate=True )
errors = irm.uninstall_repository(repository=tool_shed_repository, remove_from_disk=remove_from_disk_checked)
action = 'uninstalled' if remove_from_disk_checked else 'deactivated'
status = max( status, statuses.index( 'done' ) )
message += 'The repository named <b>%s</b> has been %s. ' % (escape( tool_shed_repository.name ), action)
if remove_from_disk_checked:
try:
# Remove the repository from disk.
shutil.rmtree( repository_install_dir )
log.debug( "Removed repository installation directory: %s" % str( repository_install_dir ) )
removed = True
except Exception as e:
log.debug( "Error removing repository installation directory %s: %s" % ( str( repository_install_dir ), str( e ) ) )
if isinstance( e, OSError ) and not os.path.exists( repository_install_dir ):
removed = True
log.debug( "Repository directory does not exist on disk, marking as uninstalled." )
else:
removed = False
if removed:
tool_shed_repository.uninstalled = True
# Remove all installed tool dependencies and tool dependencies stuck in the INSTALLING state, but don't touch any
# repository dependencies.
tool_dependencies_to_uninstall = tool_shed_repository.tool_dependencies_installed_or_in_error
tool_dependencies_to_uninstall.extend( tool_shed_repository.tool_dependencies_being_installed )
for tool_dependency in tool_dependencies_to_uninstall:
uninstalled, error_message = tool_dependency_util.remove_tool_dependency( trans.app, tool_dependency )
if error_message:
errors = '%s %s' % ( errors, error_message )
tool_shed_repository.deleted = True
if remove_from_disk_checked:
tool_shed_repository.status = trans.install_model.ToolShedRepository.installation_status.UNINSTALLED
tool_shed_repository.error_message = None
if trans.app.config.manage_dependency_relationships:
# Remove the uninstalled repository and any tool dependencies from the in-memory dictionaries in the
# installed_repository_manager.
trans.app.installed_repository_manager.handle_repository_uninstall( tool_shed_repository )
else:
tool_shed_repository.status = trans.install_model.ToolShedRepository.installation_status.DEACTIVATED
trans.install_model.context.current.add( tool_shed_repository )
trans.install_model.context.current.flush()
if remove_from_disk_checked:
message += 'The repository named <b>%s</b> has been uninstalled. ' % escape( tool_shed_repository.name )
if errors:
message += 'Attempting to uninstall tool dependencies resulted in errors: %s' % errors
status = max( status, statuses.index( 'error' ) )
else:
status = max( status, statuses.index( 'done' ) )
else:
message = 'The repository named <b>%s</b> has been deactivated. ' % escape( tool_shed_repository.name )
status = max( status, statuses.index( 'done' ) )
status = statuses[ status ]
if kwd.get( 'deactivate_or_uninstall_repository_button', False ):
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
@@ -2059,11 +1991,13 @@ class AdminToolshed( AdminGalaxy ):
tool_config = tool_metadata[ 'tool_config' ]
if shed_config_dict and shed_config_dict.get( 'tool_path' ):
tool_config = os.path.join( shed_config_dict.get( 'tool_path' ), tool_config )
tool = trans.app.toolbox.load_tool( os.path.abspath( tool_config ), guid=tool_metadata[ 'guid' ] )
tool = trans.app.toolbox.get_tool(tool_id=tool_metadata[ 'guid' ], exact=True)
if not tool:
tool = trans.app.toolbox.load_tool( os.path.abspath( tool_config ), guid=tool_metadata[ 'guid' ] )
if tool:
tool._lineage = trans.app.toolbox._lineage_map.register( tool )
if tool:
tvm = tool_version_manager.ToolVersionManager( trans.app )
tool_version = tvm.get_tool_version( str( tool.id ) )
tool_lineage = tool_version.get_version_ids( trans.app, reverse=True )
tool_lineage = tool.lineage.get_version_ids(reverse=True)
break
return trans.fill_template( "/admin/tool_shed_repository/view_tool_metadata.mako",
repository=repository,
@@ -153,7 +153,6 @@ class SharedHistoryListGrid( grids.Grid ):
# Grid definition
title = "Histories shared with you by others"
model_class = model.History
template = '/history/shared_grid.mako'
default_sort_key = "-update_time"
default_filter = {}
columns = [
@@ -164,9 +163,9 @@ class SharedHistoryListGrid( grids.Grid ):
SharedByColumn( "Shared by", key="user_id" )
]
operations = [
grids.GridOperation( "View", allow_multiple=False, target="_top" ),
grids.GridOperation( "Copy" ),
grids.GridOperation( "Unshare" )
grids.GridOperation( "View", allow_multiple=False, url_args=dict( action='view' ) ),
grids.GridOperation( "Copy", allow_multiple=False ),
grids.GridOperation( "Unshare", allow_multiple=False )
]
standard_filters = []
@@ -424,6 +423,7 @@ class HistoryController( BaseUIController, SharableMixin, UsesAnnotations, UsesI
return None, None
@web.expose
@web.json
@web.require_login( "work with shared histories" )
def list_shared( self, trans, **kwargs ):
"""List histories shared with current user by others"""
@@ -431,14 +431,10 @@ class HistoryController( BaseUIController, SharableMixin, UsesAnnotations, UsesI
if 'operation' in kwargs:
ids = galaxy.util.listify( kwargs.get( 'id', [] ) )
operation = kwargs['operation'].lower()
if operation == "view":
# Display history.
history = self.history_manager.get_accessible( self.decode_id( ids[0] ), trans.user, current_history=trans.history )
return self.display_by_username_and_slug( trans, history.user.username, history.slug )
elif operation == 'unshare':
if operation == 'unshare':
if not ids:
message = "Select a history to unshare"
return self.shared_list_grid( trans, status='error', message=message, **kwargs )
status = 'error'
for id in ids:
# No need to check security, association below won't yield a
# hit if this user isn't having the history shared with her.
@@ -451,6 +447,7 @@ class HistoryController( BaseUIController, SharableMixin, UsesAnnotations, UsesI
message = "Unshared %d shared histories" % len( ids )
status = 'done'
# Render the list view
kwargs[ 'dict_format' ] = True
return self.shared_list_grid( trans, status=status, message=message, **kwargs )
# ......................................................................... html
@@ -87,7 +87,7 @@ class Library( BaseUIController ):
}
return trans.fill_template( 'galaxy.panels.mako',
config={
'title': 'Galaxy Data Libraries',
'title': 'Data Libraries',
'app': app } )
@web.expose
+3 -3
View File
@@ -1,10 +1,10 @@
"""
This module manages loading of Galaxy webhooks.
"""
import os
import yaml
import logging
import os
import yaml
from galaxy.util import config_directories_from_setting
+2 -2
View File
@@ -1,7 +1,7 @@
from galaxy.managers.context import (
ProvidesAppContext,
ProvidesUserContext,
ProvidesHistoryContext
ProvidesHistoryContext,
ProvidesUserContext
)
+28 -18
View File
@@ -3,34 +3,44 @@ Modules used in building workflows
"""
import logging
from json import loads
from xml.etree.ElementTree import Element
from xml.etree.ElementTree import XML
from xml.etree.ElementTree import (
Element,
XML
)
from galaxy import exceptions, model, web
from galaxy.exceptions import ToolMissingException
from galaxy import (
exceptions,
model,
web
)
from galaxy.dataset_collections import matching
from galaxy.exceptions import ToolMissingException
from galaxy.jobs.actions.post import ActionBox
from galaxy.model import PostJobAction
from galaxy.tools import (
DefaultToolState,
ToolInputsNotReadyException
)
from galaxy.tools.execute import execute
from galaxy.tools.parameters import check_param
from galaxy.tools.parameters import params_to_incoming
from galaxy.tools.parameters import visit_input_values
from galaxy.tools.parameters import (
check_param,
params_to_incoming,
visit_input_values
)
from galaxy.tools.parameters.basic import (
parameter_types,
BooleanToolParameter,
TextToolParameter,
SelectToolParameter,
DataCollectionToolParameter,
DataToolParameter,
parameter_types,
RuntimeValue,
SelectToolParameter,
TextToolParameter,
workflow_building_modes
)
from galaxy.tools.parameters.wrapped import make_dict_copy
from galaxy.tools import DefaultToolState
from galaxy.tools import ToolInputsNotReadyException
from galaxy.util.odict import odict
from galaxy.util.bunch import Bunch
from galaxy.util.json import safe_loads
from galaxy.util.odict import odict
from tool_shed.util import common_util
log = logging.getLogger( __name__ )
@@ -346,7 +356,7 @@ class InputModule( WorkflowModule ):
# Web controller may set copy_inputs_to_history, API controller always sets
# inputs.
if invocation.copy_inputs_to_history:
for input_dataset_hda in step_outputs.values():
for input_dataset_hda in list(step_outputs.values()):
content_type = input_dataset_hda.history_content_type
if content_type == "dataset":
new_hda = input_dataset_hda.copy( copy_children=True )
@@ -362,7 +372,7 @@ class InputModule( WorkflowModule ):
# so do that now so dependent steps can be recalculated. In the future
# everything should come in from the API and this can be eliminated.
if not invocation.has_input_for_step( step.id ):
content = step_outputs.values()[ 0 ]
content = next(iter(step_outputs.values()))
if content:
invocation.add_input( content, step.id )
progress.set_outputs_for_input( step, step_outputs )
@@ -610,7 +620,7 @@ class ToolModule( WorkflowModule ):
super( ToolModule, self ).save_to_step( step )
step.tool_id = self.tool_id
step.tool_version = self.get_version()
for k, v in self.post_job_actions.iteritems():
for k, v in self.post_job_actions.items():
pja = self.__to_pja( k, v, step )
self.trans.sa_session.add( pja )
@@ -666,7 +676,7 @@ class ToolModule( WorkflowModule ):
def get_data_outputs( self ):
data_outputs = []
if self.tool:
for name, tool_output in self.tool.outputs.iteritems():
for name, tool_output in self.tool.outputs.items():
extra_kwds = {}
if tool_output.collection:
extra_kwds["collection"] = True
@@ -907,7 +917,7 @@ class ToolModule( WorkflowModule ):
# job actions for this execution.
flush_required = False
effective_post_job_actions = step.post_job_actions[:]
for key, value in self.runtime_post_job_actions.iteritems():
for key, value in self.runtime_post_job_actions.items():
effective_post_job_actions.append( self.__to_pja( key, value, None ) )
for pja in effective_post_job_actions:
if pja.action_type in ActionBox.immediate_actions:
+3 -3
View File
@@ -96,8 +96,8 @@ class WorkflowCanvas( object ):
else:
# Take any key / value pair available in out_conn_index_dict.
# A problem will result if the dictionary is empty.
if out_conn_index_dict.keys():
key = out_conn_index_dict.keys()[0]
if out_conn_index_dict:
key = next(iter(out_conn_index_dict.keys()))
out_conn_pos = self.out_pos[ out_pos_index ][ key ]
adjusted = ( out_conn_pos[ 0 ] + self.widths[ output_dict[ 'id' ] ], out_conn_pos[ 1 ] )
self.text.append( svgwrite.shapes.Circle(center=(out_conn_pos[ 0 ] + self.widths[ output_dict[ 'id' ] ] - MARGIN,
@@ -130,7 +130,7 @@ class WorkflowCanvas( object ):
fill = "#EBD9B2"
width = self.widths[ step_dict[ 'id' ] ]
self.add_boxes( step_dict, width, fill )
for conn, output_dict in step_dict[ 'input_connections' ].iteritems():
for conn, output_dict in step_dict[ 'input_connections' ].items():
self.add_connection( step_dict, conn, output_dict )
def populate_data_for_step( self, step, module_name, module_data_inputs, module_data_outputs, tool_errors=None ):
+9 -9
View File
@@ -1,14 +1,15 @@
import logging
import uuid
from galaxy import exceptions
from galaxy import model
from galaxy import (
exceptions,
model
)
from galaxy.managers import histories
from galaxy.tools.parameters.meta import expand_workflow_inputs
INPUT_STEP_TYPES = [ 'data_input', 'data_collection_input', 'parameter_input' ]
import logging
log = logging.getLogger( __name__ )
@@ -147,8 +148,7 @@ def _flatten_step_params( param_dict, prefix="" ):
# a complex value object versus something that maps to child parameters
# better than the hack or searching for src and id here.
new_params = {}
keys = param_dict.keys()[:]
for key in keys:
for key in list(param_dict.keys()):
if prefix:
effective_key = "%s|%s" % ( prefix, key )
else:
@@ -244,7 +244,7 @@ def build_workflow_run_configs( trans, workflow, payload ):
steps_by_id = workflow.steps_by_id
# Set workflow inputs.
for key, input_dict in normalized_inputs.iteritems():
for key, input_dict in normalized_inputs.items():
step = steps_by_id[key]
if step.type == 'parameter_input':
continue
@@ -353,13 +353,13 @@ def workflow_run_config_to_request( trans, run_config, workflow ):
)
replacement_dict = run_config.replacement_dict
for name, value in replacement_dict.iteritems():
for name, value in replacement_dict.items():
add_parameter(
name=name,
value=value,
type=param_types.REPLACEMENT_PARAMETERS,
)
for step_id, content in run_config.inputs.iteritems():
for step_id, content in run_config.inputs.items():
workflow_invocation.add_input( content, step_id )
add_parameter( "copy_inputs_to_history", "true" if run_config.copy_inputs_to_history else "false", param_types.META_PARAMETERS )
+6 -8
View File
@@ -1,16 +1,14 @@
import os
import time
import logging
import os
import threading
import time
from xml.etree import ElementTree
import galaxy.workflow.schedulers
from galaxy import model
from galaxy.util import plugin_config
from galaxy.util.handlers import ConfiguresHandlers
import galaxy.workflow.schedulers
log = logging.getLogger( __name__ )
DEFAULT_SCHEDULER_ID = "default" # well actually this should be called DEFAULT_DEFAULT_SCHEDULER_ID...
@@ -77,7 +75,7 @@ class WorkflowSchedulingManager( object, ConfiguresHandlers ):
return self.__has_handlers.get_handler( None, index=random_index )
def shutdown( self ):
for workflow_scheduler in self.workflow_schedulers.itervalues():
for workflow_scheduler in self.workflow_schedulers.values():
try:
workflow_scheduler.shutdown()
except Exception:
@@ -103,7 +101,7 @@ class WorkflowSchedulingManager( object, ConfiguresHandlers ):
return workflow_invocation
def __start_schedulers( self ):
for workflow_scheduler in self.workflow_schedulers.itervalues():
for workflow_scheduler in self.workflow_schedulers.values():
workflow_scheduler.startup( self.app )
def __plugins_dict( self ):
@@ -185,7 +183,7 @@ class WorkflowRequestMonitor( object ):
def __monitor( self ):
to_monitor = self.workflow_scheduling_manager.active_workflow_schedulers
while self.active:
for workflow_scheduler_id, workflow_scheduler in to_monitor.iteritems():
for workflow_scheduler_id, workflow_scheduler in to_monitor.items():
if not self.active:
return
+1 -2
View File
@@ -1,9 +1,8 @@
# override tempfile methods for debugging
import logging
import tempfile
import traceback
import logging
log = logging.getLogger( __name__ )
@@ -4,6 +4,7 @@ Class encapsulating the management of repositories installed into Galaxy from th
import copy
import logging
import os
import shutil
from sqlalchemy import and_, false, true
@@ -78,11 +79,11 @@ class InstalledRepositoryManager( object ):
def activate_repository( self, repository ):
"""Activate an installed tool shed repository that has been marked as deactivated."""
repository_clone_url = common_util.generate_clone_url_for_installed_repository( self.app, repository )
shed_tool_conf, tool_path, relative_install_dir = suc.get_tool_panel_config_tool_path_install_dir( self.app, repository )
repository.deleted = False
repository.status = self.install_model.ToolShedRepository.installation_status.INSTALLED
if repository.includes_tools_for_display_in_tool_panel:
repository_clone_url = common_util.generate_clone_url_for_installed_repository( self.app, repository )
tpm = tool_panel_manager.ToolPanelManager( self.app )
irmm = InstalledRepositoryMetadataManager( app=self.app,
tpm=tpm,
@@ -749,6 +750,75 @@ class InstalledRepositoryManager( object ):
if installed_repository_dict[ 'display_path' ]:
cdl.load_installed_display_applications( installed_repository_dict, deactivate=deactivate )
def uninstall_repository(self, repository, remove_from_disk=True):
errors = ''
shed_tool_conf, tool_path, relative_install_dir = \
suc.get_tool_panel_config_tool_path_install_dir( app=self.app, repository=repository )
if relative_install_dir:
if tool_path:
relative_install_dir = os.path.join( tool_path, relative_install_dir )
repository_install_dir = os.path.abspath( relative_install_dir )
else:
repository_install_dir = None
if repository.includes_tools_for_display_in_tool_panel:
# Handle tool panel alterations.
tpm = tool_panel_manager.ToolPanelManager(app=self.app)
tpm.remove_repository_contents(repository,
shed_tool_conf,
uninstall=remove_from_disk)
if repository.includes_data_managers:
dmh = data_manager.DataManagerHandler(app=self.app)
dmh.remove_from_data_manager(repository)
if repository.includes_datatypes:
# Deactivate proprietary datatypes.
cdl = custom_datatype_manager.CustomDatatypeLoader(app=self.app)
installed_repository_dict = cdl.load_installed_datatypes( repository,
repository_install_dir,
deactivate=True )
if installed_repository_dict:
converter_path = installed_repository_dict.get( 'converter_path' )
if converter_path is not None:
cdl.load_installed_datatype_converters( installed_repository_dict, deactivate=True )
display_path = installed_repository_dict.get( 'display_path' )
if display_path is not None:
cdl.load_installed_display_applications( installed_repository_dict, deactivate=True )
if remove_from_disk:
try:
# Remove the repository from disk.
shutil.rmtree( repository_install_dir )
log.debug( "Removed repository installation directory: %s" % str( repository_install_dir ) )
removed = True
except Exception as e:
log.debug( "Error removing repository installation directory %s: %s" % ( str( repository_install_dir ), str( e ) ) )
if isinstance( e, OSError ) and not os.path.exists( repository_install_dir ):
removed = True
log.debug( "Repository directory does not exist on disk, marking as uninstalled." )
else:
removed = False
if removed:
repository.uninstalled = True
# Remove all installed tool dependencies and tool dependencies stuck in the INSTALLING state, but don't touch any
# repository dependencies.
tool_dependencies_to_uninstall = repository.tool_dependencies_installed_or_in_error
tool_dependencies_to_uninstall.extend( repository.tool_dependencies_being_installed )
for tool_dependency in tool_dependencies_to_uninstall:
uninstalled, error_message = tool_dependency_util.remove_tool_dependency( self.app, tool_dependency )
if error_message:
errors = '%s %s' % ( errors, error_message )
repository.deleted = True
if remove_from_disk:
repository.status = self.app.install_model.ToolShedRepository.installation_status.UNINSTALLED
repository.error_message = None
if self.app.config.manage_dependency_relationships:
# Remove the uninstalled repository and any tool dependencies from the in-memory dictionaries in the
# installed_repository_manager.
self.handle_repository_uninstall( repository )
else:
repository.status = self.app.install_model.ToolShedRepository.installation_status.DEACTIVATED
self.app.install_model.context.current.add( repository )
self.app.install_model.context.current.flush()
return errors
def purge_repository( self, repository ):
"""Purge a repository with status New (a white ghost) from the database."""
sa_session = self.app.model.context.current
@@ -2,7 +2,6 @@ import logging
from sqlalchemy import and_, or_
from galaxy.tools.toolbox.lineages.tool_shed import ToolVersionCache
from tool_shed.util import hg_util
from tool_shed.util import metadata_util
from tool_shed.util import repository_util
@@ -112,4 +111,3 @@ class ToolVersionManager( object ):
parent_id=tool_version_using_parent_id.id )
context.add( tool_version_association )
context.flush()
self.app.tool_version_cache = ToolVersionCache(self.app)
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"history-list.js","sources":["../../../src/mvc/history/history-list.js"],"names":["define","Utils","GridView","HistoryModel","historyCopyDialog","View","Backbone","extend","initialize","self","this","setElement","$","model","Model","get","url","Galaxy","root","success","response","_","each","operation","label","onclick","id","_showCopyDialog","set","render","grid","attributes","$el","empty","append","history","History","fetch","fail","alert","done","window","parent","currHistoryPanel","loadCurrentHistory","location","reload"],"mappings":"AACAA,QAAU,cAAe,qBAAsB,4BAA6B,2BAA6B,SAAUC,EAAOC,EAAUC,EAAcC,GAE9I,GAAIC,GAAOC,SAASD,KAAKE,QACrBC,WAAY,WACR,GAAIC,GAAOC,IACXA,MAAKC,WAAYC,EAAG,WACpBF,KAAKG,MAAQ,GAAIP,UAASQ,MAC1Bb,EAAMc,KACFC,IAAUC,OAAOC,KAAO,eACxBC,QAAU,SAAUC,GAChBA,EAAwB,aAAI,EAC5BC,EAAEC,KAAMF,EAAuB,WAAG,SAAUG,GAChB,QAAnBA,EAAUC,QACXD,EAAUE,QAAU,SAAUC,GAAOjB,EAAKkB,gBAAiBD,OAGnEjB,EAAKI,MAAMe,IAAKR,GAChBX,EAAKoB,aAKjBA,OAAQ,WACJ,GAAIC,GAAO,GAAI5B,GAAUQ,KAAKG,MAAMkB,WACpCrB,MAAKsB,IAAIC,QAAQC,OAAQJ,EAAKE,MAGlCL,gBAAiB,SAAUD,GACvB,GAAIS,GAAU,GAAIhC,GAAaiC,SAAWV,GAAKA,GAC/CS,GAAQE,QACAC,KAAM,WACHC,MAAO,mEAEVC,KAAM,WACHpC,EAAmB+B,MAAcK,KAAM,WAC/BC,OAAOC,QAAUD,OAAOC,OAAOzB,QAAUwB,OAAOC,OAAOzB,OAAO0B,kBAC9DF,OAAOC,OAAOzB,OAAO0B,iBAAiBC,qBAE1CH,OAAOI,SAASC,QAAQ,SAM/C,QACIzC,KAAMA"}
{"version":3,"file":"history-list.js","sources":["../../../src/mvc/history/history-list.js"],"names":["define","Utils","GridView","HistoryModel","historyCopyDialog","View","Backbone","extend","initialize","options","self","this","setElement","$","model","Model","get","url","Galaxy","root","action_id","success","response","_","each","operation","label","onclick","id","_showCopyDialog","set","render","grid","attributes","$el","empty","append","history","History","fetch","fail","alert","done","window","parent","currHistoryPanel","loadCurrentHistory","location","reload"],"mappings":"AACAA,QAAU,cAAe,qBAAsB,4BAA6B,2BAA6B,SAAUC,EAAOC,EAAUC,EAAcC,GAE9I,GAAIC,GAAOC,SAASD,KAAKE,QACrBC,WAAY,SAAUC,GAClB,GAAIC,GAAOC,IACXA,MAAKC,WAAYC,EAAG,WACpBF,KAAKG,MAAQ,GAAIR,UAASS,MAC1Bd,EAAMe,KACFC,IAAUC,OAAOC,KAAO,WAAaV,EAAQW,UAC7CC,QAAU,SAAUC,GAChBA,EAAwB,aAAI,EAC5BC,EAAEC,KAAMF,EAAuB,WAAG,SAAUG,GAChB,QAAnBA,EAAUC,QACXD,EAAUE,QAAU,SAAUC,GAAOlB,EAAKmB,gBAAiBD,OAGnElB,EAAKI,MAAMgB,IAAKR,GAChBZ,EAAKqB,aAKjBA,OAAQ,WACJ,GAAIC,GAAO,GAAI9B,GAAUS,KAAKG,MAAMmB,WACpCtB,MAAKuB,IAAIC,QAAQC,OAAQJ,EAAKE,MAGlCL,gBAAiB,SAAUD,GACvB,GAAIS,GAAU,GAAIlC,GAAamC,SAAWV,GAAKA,GAC/CS,GAAQE,QACAC,KAAM,WACHC,MAAO,mEAEVC,KAAM,WACHtC,EAAmBiC,MAAcK,KAAM,WAC/BC,OAAOC,QAAUD,OAAOC,OAAO1B,QAAUyB,OAAOC,OAAO1B,OAAO2B,kBAC9DF,OAAOC,OAAO1B,OAAO2B,iBAAiBC,qBAE1CH,OAAOI,SAASC,QAAQ,SAM/C,QACI3C,KAAMA"}
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"options-menu.js","sources":["../../../src/mvc/history/options-menu.js"],"names":["define","PopupMenu","historyCopyDialog","BASE_MVC","_l","Webhooks","buildMenu","isAnon","purgeAllowed","urlRoot","_","clone","menu","filter","menuOption","anon","purge","href","target","confirm","func","galaxy_main","location","html","header","Galaxy","currHistoryPanel","createNewHistory","model","done","loadCurrentHistory","window","id","collapseAll","$","post","root","user_action","add","url","async","callback","webhooks","webhooks_menu","each","models","index","webhook","toJSON","activate","push","config","title","length","unshift","merge","create","$button","options","undefined","anonymous"],"mappings":"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"}
{"version":3,"file":"options-menu.js","sources":["../../../src/mvc/history/options-menu.js"],"names":["define","PopupMenu","historyCopyDialog","BASE_MVC","_l","Webhooks","buildMenu","isAnon","purgeAllowed","urlRoot","_","clone","menu","filter","menuOption","anon","purge","href","target","confirm","func","galaxy_main","location","html","header","Galaxy","currHistoryPanel","createNewHistory","model","done","loadCurrentHistory","window","id","collapseAll","$","post","root","user_action","add","url","async","callback","webhooks","webhooks_menu","each","models","index","webhook","toJSON","activate","push","config","title","length","unshift","merge","create","$button","options","undefined","anonymous"],"mappings":"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"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More