galaxy-dev
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
September 2009
- 15 participants
- 140 discussions
details: http://www.bx.psu.edu/hg/galaxy/rev/ce8c57840343
changeset: 2673:ce8c57840343
user: Nate Coraor <nate(a)bx.psu.edu>
date: Thu Sep 10 17:31:05 2009 -0400
description:
POSIXize/Bournize updateucsc.sh.sample
1 file(s) affected in this change:
cron/updateucsc.sh.sample
diffs (57 lines):
diff -r d3fe789e3931 -r ce8c57840343 cron/updateucsc.sh.sample
--- a/cron/updateucsc.sh.sample Thu Sep 10 14:52:38 2009 -0400
+++ b/cron/updateucsc.sh.sample Thu Sep 10 17:31:05 2009 -0400
@@ -6,7 +6,8 @@
# Edit this line to refer to galaxy's path:
GALAXY=/galaxy/path
-export PYTHONPATH=${GALAXY}/lib
+PYTHONPATH=${GALAXY}/lib
+export PYTHONPATH
# setup directories
echo "Creating required directories."
@@ -32,7 +33,11 @@
python ${GALAXY}/cron/parse_builds.py > ${GALAXY}/tool-data/shared/ucsc/new/builds.txt
if [ $? -eq 0 ]
then
- cp -uf ${GALAXY}/tool-data/shared/ucsc/new/builds.txt ${GALAXY}/tool-data/shared/ucsc/builds.txt
+ diff ${GALAXY}/tool-data/shared/ucsc/new/builds.txt ${GALAXY}/tool-data/shared/ucsc/builds.txt > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ cp -f ${GALAXY}/tool-data/shared/ucsc/new/builds.txt ${GALAXY}/tool-data/shared/ucsc/builds.txt
+ fi
else
echo "Failed to update builds.txt" >&2
fi
@@ -42,7 +47,11 @@
python ${GALAXY}/cron/parse_builds_3_sites.py > ${GALAXY}/tool-data/shared/ucsc/new/ucsc_build_sites.txt
if [ $? -eq 0 ]
then
- cp -uf ${GALAXY}/tool-data/shared/ucsc/new/ucsc_build_sites.txt ${GALAXY}/tool-data/shared/ucsc/ucsc_build_sites.txt
+ diff ${GALAXY}/tool-data/shared/ucsc/new/ucsc_build_sites.txt ${GALAXY}/tool-data/shared/ucsc/ucsc_build_sites.txt > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ cp -f ${GALAXY}/tool-data/shared/ucsc/new/ucsc_build_sites.txt ${GALAXY}/tool-data/shared/ucsc/ucsc_build_sites.txt
+ fi
else
echo "Failed to update builds.txt" >&2
fi
@@ -52,7 +61,16 @@
python ${GALAXY}/cron/build_chrom_db.py ${GALAXY}/tool-data/shared/ucsc/chrom/new/ ${GALAXY}/tool-data/shared/ucsc/builds.txt
if [ $? -eq 0 ]
then
- cp -uf ${GALAXY}/tool-data/shared/ucsc/chrom/new/*.len ${GALAXY}/tool-data/shared/ucsc/chrom/
+ for src in ${GALAXY}/tool-data/shared/ucsc/chrom/new/*.len
+ do
+ dst=${GALAXY}/tool-data/shared/ucsc/chrom/`basename $src`
+ diff $src $dst > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ echo "cp -f $src $dst"
+ cp -f $src $dst
+ fi
+ done
else
echo "Failed to update chromInfo tables." >&2
fi
1
0
10 Sep '09
details: http://www.bx.psu.edu/hg/galaxy/rev/d3fe789e3931
changeset: 2672:d3fe789e3931
user: Nate Coraor <nate(a)bx.psu.edu>
date: Thu Sep 10 14:52:38 2009 -0400
description:
Get rid of the hacky "alternate path" stuff used by the upload tool and fix setting metadata when using autodetect and set_metadata_externally
4 file(s) affected in this change:
lib/galaxy/jobs/__init__.py
lib/galaxy/tools/actions/upload.py
tools/data_source/upload.py
tools/data_source/upload.xml
diffs (151 lines):
diff -r dbbc63c0630a -r d3fe789e3931 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py Thu Sep 10 10:42:50 2009 -0400
+++ b/lib/galaxy/jobs/__init__.py Thu Sep 10 14:52:38 2009 -0400
@@ -502,13 +502,6 @@
context = self.get_dataset_finish_context( job_context, dataset_assoc.dataset.dataset )
#should this also be checking library associations? - can a library item be added from a history before the job has ended? - lets not allow this to occur
for dataset in dataset_assoc.dataset.dataset.history_associations: #need to update all associated output hdas, i.e. history was shared with job running
- if context.get( 'path', None ):
- # The tool can set an alternate output path for the dataset.
- try:
- shutil.move( context['path'], dataset.file_name )
- except ( IOError, OSError ):
- if not context['stderr']:
- context['stderr'] = 'This dataset could not be processed'
dataset.blurb = 'done'
dataset.peek = 'no peek'
dataset.info = context['stdout'] + context['stderr']
@@ -707,6 +700,13 @@
sizes.append( ( outfile, os.stat( outfile ).st_size ) )
return sizes
def setup_external_metadata( self, exec_dir = None, tmp_dir = None, dataset_files_path = None, config_root = None, datatypes_config = None, **kwds ):
+ # extension could still be 'auto' if this is the upload tool.
+ job = model.Job.get( self.job_id )
+ for output_dataset_assoc in job.output_datasets:
+ if output_dataset_assoc.dataset.ext == 'auto':
+ context = self.get_dataset_finish_context( dict(), output_dataset_assoc.dataset.dataset )
+ output_dataset_assoc.dataset.extension = context.get( 'ext', 'data' )
+ mapping.context.current.flush()
if tmp_dir is None:
#this dir should should relative to the exec_dir
tmp_dir = self.app.config.new_file_path
@@ -716,7 +716,6 @@
config_root = self.app.config.root
if datatypes_config is None:
datatypes_config = self.app.config.datatypes_config
- job = model.Job.get( self.job_id )
return self.external_output_metadata.setup_external_metadata( [ output_dataset_assoc.dataset for output_dataset_assoc in job.output_datasets ], exec_dir = exec_dir, tmp_dir = tmp_dir, dataset_files_path = dataset_files_path, config_root = config_root, datatypes_config = datatypes_config, **kwds )
class DefaultJobDispatcher( object ):
diff -r dbbc63c0630a -r d3fe789e3931 lib/galaxy/tools/actions/upload.py
--- a/lib/galaxy/tools/actions/upload.py Thu Sep 10 10:42:50 2009 -0400
+++ b/lib/galaxy/tools/actions/upload.py Thu Sep 10 14:52:38 2009 -0400
@@ -144,7 +144,7 @@
job.add_parameter( name, value )
job.add_parameter( 'paramfile', to_json_string( json_file_path ) )
for i, dataset in enumerate( data_list ):
- job.add_output_dataset( i, dataset )
+ job.add_output_dataset( 'output%i' % i, dataset )
job.state = trans.app.model.Job.states.NEW
trans.app.model.flush()
diff -r dbbc63c0630a -r d3fe789e3931 tools/data_source/upload.py
--- a/tools/data_source/upload.py Thu Sep 10 10:42:50 2009 -0400
+++ b/tools/data_source/upload.py Thu Sep 10 14:52:38 2009 -0400
@@ -115,7 +115,14 @@
return ( True, False, test_ext )
return ( True, True, test_ext )
-def add_file( dataset, json_file ):
+def parse_outputs( args ):
+ rval = {}
+ for arg in args:
+ id, path = arg.split( ':', 1 )
+ rval[int( id )] = path
+ return rval
+
+def add_file( dataset, json_file, output_path ):
data_type = None
line_count = None
@@ -229,16 +236,18 @@
ext = dataset.ext
if ext == 'auto':
ext = 'data'
+ # Move the dataset to its "real" path
+ shutil.move( dataset.path, output_path )
+ # Write the job info
info = dict( type = 'dataset',
dataset_id = dataset.dataset_id,
- path = dataset.path,
ext = ext,
stdout = 'uploaded %s file' % data_type,
name = dataset.name,
line_count = line_count )
json_file.write( to_json_string( info ) + "\n" )
-def add_composite_file( dataset, json_file ):
+def add_composite_file( dataset, json_file, output_path ):
if dataset.composite_files:
os.mkdir( dataset.extra_files_path )
for name, value in dataset.composite_files.iteritems():
@@ -253,17 +262,21 @@
else:
sniff.convert_newlines( dataset.composite_file_paths[ value.name ][ 'path' ] )
shutil.move( dataset.composite_file_paths[ value.name ][ 'path' ], os.path.join( dataset.extra_files_path, name ) )
+ # Move the dataset to its "real" path
+ shutil.move( dataset.primary_file, output_path )
+ # Write the job info
info = dict( type = 'dataset',
dataset_id = dataset.dataset_id,
- path = dataset.primary_file,
stdout = 'uploaded %s file' % dataset.file_type )
json_file.write( to_json_string( info ) + "\n" )
def __main__():
- if len( sys.argv ) != 2:
- print >>sys.stderr, 'usage: upload.py <json paramfile>'
+ if len( sys.argv ) < 2:
+ print >>sys.stderr, 'usage: upload.py <json paramfile> <output spec> ...'
sys.exit( 1 )
+
+ output_paths = parse_outputs( sys.argv[2:] )
json_file = open( 'galaxy.json', 'w' )
@@ -271,10 +284,16 @@
dataset = from_json_string( line )
dataset = util.bunch.Bunch( **safe_dict( dataset ) )
+ try:
+ output_path = output_paths[int( dataset.dataset_id )]
+ except:
+ print >>sys.stderr, 'Output path for dataset %s not found on command line' % dataset.dataset_id
+ sys.exit( 1 )
+
if dataset.type == 'composite':
- add_composite_file( dataset, json_file )
+ add_composite_file( dataset, json_file, output_path )
else:
- add_file( dataset, json_file )
+ add_file( dataset, json_file, output_path )
# clean up paramfile
try:
diff -r dbbc63c0630a -r d3fe789e3931 tools/data_source/upload.xml
--- a/tools/data_source/upload.xml Thu Sep 10 10:42:50 2009 -0400
+++ b/tools/data_source/upload.xml Thu Sep 10 14:52:38 2009 -0400
@@ -7,6 +7,12 @@
<action module="galaxy.tools.actions.upload" class="UploadToolAction"/>
<command interpreter="python">
upload.py $paramfile
+ #set $outnum = 0
+ #while $varExists('output%i' % $outnum):
+ #set $output = $getVar('output%i' % $outnum)
+ #set $outnum += 1
+ ${output.dataset.dataset.id}:${output}
+ #end while
</command>
<inputs>
<param name="file_type" type="select" label="File Format" help="Which format? See help below">
1
0
10 Sep '09
details: http://www.bx.psu.edu/hg/galaxy/rev/dbbc63c0630a
changeset: 2671:dbbc63c0630a
user: guru
date: Thu Sep 10 10:42:50 2009 -0400
description:
Updated manual builds will L. major (2005) genome.
1 file(s) affected in this change:
tool-data/shared/ucsc/manual_builds.txt
diffs (8 lines):
diff -r c3b40f23a0e0 -r dbbc63c0630a tool-data/shared/ucsc/manual_builds.txt
--- a/tool-data/shared/ucsc/manual_builds.txt Wed Sep 09 14:24:11 2009 -0400
+++ b/tool-data/shared/ucsc/manual_builds.txt Thu Sep 10 10:42:50 2009 -0400
@@ -664,3 +664,4 @@
baciAnth_AMES Bacillus anthracis str. Ames chr=5227293
shewOnei Shewanella oneidensis MR-1 plasmid_pMR-1=161613,chr=4969803
15217 Human herpesvirus 1 NC_001806=152261
+lMaj5 Leishmania major 2005 chr1=268984,chr2=355714,chr3=384518,chr4=441313,chr5=465823,chr6=516874,chr7=596348,chr8=574972,chr9=573441,chr10=570864,chr11=582575,chr12=675347,chr13=654604,chr14=622648,chr15=629514,chr16=714659,chr17=684831,chr18=739751,chr19=702212,chr20=742551,chr21=772974,chr22=716608,chr23=772567,chr24=840950,chr25=912849,chr26=1091579,chr27=1130447,chr28=1160128,chr29=1212674,chr30=1403454,chr31=1484336,chr32=1604650,chr33=1583673,chr34=1866754,chr35=2090491,chr36=2682183
1
0
Hi,
I am looking for more information on the options in the Logging and
Debugging section of the universe_wsgi.ini file, in particular what
are specific values to which I can set log_level in the first option
"verbosity of log messages".
I wish to turn off the debugging messages in the log file.
Thanks
Shaun Webb
--
The University of Edinburgh is a charitable body, registered in
Scotland, with registration number SC005336.
2
1
09 Sep '09
details: http://www.bx.psu.edu/hg/galaxy/rev/c3b40f23a0e0
changeset: 2670:c3b40f23a0e0
user: James Taylor <james(a)jamestaylor.org>
date: Wed Sep 09 14:24:11 2009 -0400
description:
Automated merge with http://bitbucket.org/galaxy/galaxy-central/
2 file(s) affected in this change:
lib/galaxy/model/__init__.py
templates/dataset/edit_attributes.mako
diffs (truncated from 7595 to 3000 lines):
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/datatypes/converters/maf_to_fasta_converter.py
--- a/lib/galaxy/datatypes/converters/maf_to_fasta_converter.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/datatypes/converters/maf_to_fasta_converter.py Wed Sep 09 14:24:11 2009 -0400
@@ -14,12 +14,15 @@
input_name = sys.argv.pop(1)
out = open( output_name, 'w' )
count = 0
- for count, maf in enumerate( bx.align.maf.Reader( open( input_name, 'r' ) ) ):
- for c in maf.components:
- spec, chrom = bx.align.maf.src_split( c.src )
- if not spec or not chrom:
- spec = chrom = c.src
- out.write( "%s\n" % maf_utilities.get_fasta_header( c, suffix = "%s_%i" % ( spec, count ) ) )
+ for count, block in enumerate( bx.align.maf.Reader( open( input_name, 'r' ) ) ):
+ spec_counts = {}
+ for c in block.components:
+ spec, chrom = maf_utilities.src_split( c.src )
+ if spec not in spec_counts:
+ spec_counts[ spec ] = 0
+ else:
+ spec_counts[ spec ] += 1
+ out.write( "%s\n" % maf_utilities.get_fasta_header( c, { 'block_index' : count, 'species' : spec, 'sequence_index' : spec_counts[ spec ] }, suffix = "%s_%i_%i" % ( spec, count, spec_counts[ spec ] ) ) )
out.write( "%s\n" % c.text )
out.write( "\n" )
out.close()
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/datatypes/converters/maf_to_fasta_converter.xml
--- a/lib/galaxy/datatypes/converters/maf_to_fasta_converter.xml Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/datatypes/converters/maf_to_fasta_converter.xml Wed Sep 09 14:24:11 2009 -0400
@@ -1,4 +1,4 @@
-<tool id="CONVERTER_maf_to_fasta_0" name="Convert MAF to Fasta">
+<tool id="CONVERTER_maf_to_fasta_0" name="Convert MAF to Fasta" version="1.0.1">
<!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
<command interpreter="python">maf_to_fasta_converter.py $output1 $input1</command>
<inputs>
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/datatypes/converters/maf_to_interval_converter.py
--- a/lib/galaxy/datatypes/converters/maf_to_interval_converter.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/datatypes/converters/maf_to_interval_converter.py Wed Sep 09 14:24:11 2009 -0400
@@ -4,7 +4,8 @@
import sys
from galaxy import eggs
import pkg_resources; pkg_resources.require( "bx-python" )
-import bx.align.maf
+import bx.align.maf
+from galaxy.tools.util import maf_utilities
assert sys.version_info[:2] >= ( 2, 4 )
@@ -17,15 +18,15 @@
#write interval header line
out.write( "#chrom\tstart\tend\tstrand\n" )
try:
- for maf in bx.align.maf.Reader( open(input_name, 'r') ):
- c = maf.get_component_by_src_start(species)
- if c is not None:
- out.write( "%s\t%i\t%i\t%s\n" % (bx.align.src_split(c.src)[-1], c.get_forward_strand_start(), c.get_forward_strand_end(), c.strand) )
- count += 1
+ for block in bx.align.maf.Reader( open( input_name, 'r' ) ):
+ for c in maf_utilities.iter_components_by_src_start( block, species ):
+ if c is not None:
+ out.write( "%s\t%i\t%i\t%s\n" % ( bx.align.src_split( c.src )[-1], c.get_forward_strand_start(), c.get_forward_strand_end(), c.strand ) )
+ count += 1
except Exception, e:
print >> sys.stderr, "There was a problem processing your input: %s" % e
out.close()
- print "%i MAF blocks converted to Genomic Intervals for species %s." % (count, species)
+ print "%i MAF blocks converted to Genomic Intervals for species %s." % ( count, species )
if __name__ == "__main__": __main__()
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/datatypes/converters/maf_to_interval_converter.xml
--- a/lib/galaxy/datatypes/converters/maf_to_interval_converter.xml Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/datatypes/converters/maf_to_interval_converter.xml Wed Sep 09 14:24:11 2009 -0400
@@ -1,4 +1,4 @@
-<tool id="CONVERTER_maf_to_interval_0" name="Convert MAF to Genomic Intervals">
+<tool id="CONVERTER_maf_to_interval_0" name="Convert MAF to Genomic Intervals" version="1.0.1">
<!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
<command interpreter="python">maf_to_interval_converter.py $output1 $input1 ${input1.metadata.dbkey}</command>
<inputs>
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/datatypes/sequence.py
--- a/lib/galaxy/datatypes/sequence.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/datatypes/sequence.py Wed Sep 09 14:24:11 2009 -0400
@@ -22,7 +22,7 @@
pass
class Alignment( Sequence ):
- """Class describing an alignmnet"""
+ """Class describing an alignment"""
"""Add metadata elements"""
MetadataElement( name="species", desc="Species", default=[], param=metadata.SelectParameter, multiple=True, readonly=True, no_value=None )
@@ -316,6 +316,78 @@
import bx.align.maf
except:
pass
+#trying to import maf_utilities here throws an ImportError due to a circular import between jobs and tools:
+#from galaxy.tools.util.maf_utilities import build_maf_index_species_chromosomes
+#Traceback (most recent call last):
+# File "./scripts/paster.py", line 27, in <module>
+# command.run()
+# File "build/bdist.solaris-2.11-i86pc/egg/paste/script/command.py", line 78, in run
+# File "build/bdist.solaris-2.11-i86pc/egg/paste/script/command.py", line 117, in invoke
+# File "build/bdist.solaris-2.11-i86pc/egg/paste/script/command.py", line 212, in run
+# File "build/bdist.solaris-2.11-i86pc/egg/paste/script/serve.py", line 227, in command
+# File "build/bdist.solaris-2.11-i86pc/egg/paste/script/serve.py", line 250, in loadapp
+# File "build/bdist.solaris-2.11-i86pc/egg/paste/deploy/loadwsgi.py", line 193, in loadapp
+# File "build/bdist.solaris-2.11-i86pc/egg/paste/deploy/loadwsgi.py", line 213, in loadobj
+# File "build/bdist.solaris-2.11-i86pc/egg/paste/deploy/loadwsgi.py", line 237, in loadcontext
+# File "build/bdist.solaris-2.11-i86pc/egg/paste/deploy/loadwsgi.py", line 267, in _loadconfig
+# File "build/bdist.solaris-2.11-i86pc/egg/paste/deploy/loadwsgi.py", line 397, in get_context
+# File "build/bdist.solaris-2.11-i86pc/egg/paste/deploy/loadwsgi.py", line 439, in _context_from_explicit
+# File "build/bdist.solaris-2.11-i86pc/egg/paste/deploy/loadwsgi.py", line 18, in import_string
+# File "/afs/bx.psu.edu/home/dan/galaxy/central/lib/pkg_resources.py", line 1912, in load
+# entry = __import__(self.module_name, globals(),globals(), ['__name__'])
+# File "/afs/bx.psu.edu/home/dan/galaxy/central/lib/galaxy/web/buildapp.py", line 18, in <module>
+# from galaxy import config, jobs, util, tools
+# File "/afs/bx.psu.edu/home/dan/galaxy/central/lib/galaxy/jobs/__init__.py", line 3, in <module>
+# from galaxy import util, model
+# File "/afs/bx.psu.edu/home/dan/galaxy/central/lib/galaxy/model/__init__.py", line 13, in <module>
+# import galaxy.datatypes.registry
+# File "/afs/bx.psu.edu/home/dan/galaxy/central/lib/galaxy/datatypes/registry.py", line 6, in <module>
+# import data, tabular, interval, images, sequence, qualityscore, genetics, xml, coverage, tracks, chrominfo
+# File "/afs/bx.psu.edu/home/dan/galaxy/central/lib/galaxy/datatypes/sequence.py", line 344, in <module>
+# from galaxy.tools.util.maf_utilities import build_maf_index_species_chromosomes
+# File "/afs/bx.psu.edu/home/dan/galaxy/central/lib/galaxy/tools/__init__.py", line 15, in <module>
+# from galaxy import util, jobs, model
+#ImportError: cannot import name jobs
+#so we'll copy and paste for now...terribly icky
+#*** ANYCHANGE TO THIS METHOD HERE OR IN maf_utilities MUST BE PROPAGATED ***
+def COPIED_build_maf_index_species_chromosomes( filename, index_species = None ):
+ species = []
+ species_chromosomes = {}
+ indexes = bx.interval_index_file.Indexes()
+ try:
+ maf_reader = bx.align.maf.Reader( open( filename ) )
+ while True:
+ pos = maf_reader.file.tell()
+ block = maf_reader.next()
+ if block is None: break
+ for c in block.components:
+ spec = c.src
+ chrom = None
+ if "." in spec:
+ spec, chrom = spec.split( ".", 1 )
+ if spec not in species:
+ species.append( spec )
+ species_chromosomes[spec] = []
+ if chrom and chrom not in species_chromosomes[spec]:
+ species_chromosomes[spec].append( chrom )
+ if index_species is None or spec in index_species:
+ forward_strand_start = c.forward_strand_start
+ forward_strand_end = c.forward_strand_end
+ try:
+ forward_strand_start = int( forward_strand_start )
+ forward_strand_end = int( forward_strand_end )
+ except ValueError:
+ continue #start and end are not integers, can't add component to index, goto next component
+ #this likely only occurs when parse_e_rows is True?
+ #could a species exist as only e rows? should the
+ if forward_strand_end > forward_strand_start:
+ #require positive length; i.e. certain lines have start = end = 0 and cannot be indexed
+ indexes.add( c.src, forward_strand_start, forward_strand_end, pos, max=c.src_size )
+ except Exception, e:
+ #most likely a bad MAF
+ log.debug( 'Building MAF index on %s failed: %s' % ( filename, e ) )
+ return ( None, [], {} )
+ return ( indexes, species, species_chromosomes )
class Maf( Alignment ):
"""Class describing a Maf alignment"""
@@ -333,38 +405,8 @@
Parses and sets species, chromosomes, index from MAF file.
"""
#these metadata values are not accessable by users, always overwrite
+ indexes, species, species_chromosomes = COPIED_build_maf_index_species_chromosomes( dataset.file_name )
- try:
- maf_reader = bx.align.maf.Reader( open( dataset.file_name ) )
- except:
- return #not a maf file
- species = []
- species_chromosomes = {}
- indexes = bx.interval_index_file.Indexes()
- while True:
- pos = maf_reader.file.tell()
- block = maf_reader.next()
- if block is None: break
- for c in block.components:
- spec = c.src
- chrom = None
- if "." in spec:
- spec, chrom = spec.split( ".", 1 )
- if spec not in species:
- species.append(spec)
- species_chromosomes[spec] = []
- if chrom and chrom not in species_chromosomes[spec]:
- species_chromosomes[spec].append( chrom )
- forward_strand_start = c.forward_strand_start
- forward_strand_end = c.forward_strand_end
- try:
- forward_strand_start = int( forward_strand_start )
- forward_strand_end = int( forward_strand_end )
- except ValueError:
- continue #start and end are not integers, can't add component to index, goto next component
- if forward_strand_end > forward_strand_start:
- #require positive length; i.e. certain lines have start = end = 0 and cannot be indexed
- indexes.add( c.src, forward_strand_start, forward_strand_end, pos, max=c.src_size )
dataset.metadata.species = species
#only overwrite the contents if our newly determined chromosomes don't match stored
chrom_file = dataset.metadata.species_chromosomes
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/model/__init__.py Wed Sep 09 14:24:11 2009 -0400
@@ -709,9 +709,9 @@
folder.order_id = self.item_count
self.item_count += 1
def get_info_association( self, restrict=False ):
- # If restrict is True, we will return this folder's info_association whether it
- # exists or not. If restrict is False, we'll return the next available info_association
- # in the inheritable hierarchy
+ # If restrict is True, we will return this folder's info_association, not inheriting.
+ # If restrict is False, we'll return the next available info_association in the
+ # inheritable hierarchy
if self.info_association:
return self.info_association[0]
if restrict:
@@ -721,9 +721,6 @@
if self.library_root:
return self.library_root[0].get_info_association()
return None
- @property
- def active_components( self ):
- return list( self.active_folders ) + list( self.active_library_datasets )
@property
def active_library_datasets( self ):
# This needs to be a list
@@ -736,10 +733,6 @@
def active_datasets( self ):
# This needs to be a list
return [ ld.library_dataset_dataset_association.dataset for ld in self.datasets if not ld.library_dataset_dataset_association.deleted ]
- @property #make this a relation
- def activatable_folders( self ):
- # This needs to be a list
- return [ folder for folder in self.folders if not folder.purged ]
class LibraryDataset( object ):
# This class acts as a proxy to the currently selected LDDA
@@ -1062,17 +1055,11 @@
return s
return False
def submitted(self):
- if self.state == self.states.SUBMITTED:
- return True
- return False
+ return self.state == self.states.SUBMITTED
def unsubmitted(self):
- if self.state == self.states.UNSUBMITTED:
- return True
- return False
+ return self.state == self.states.UNSUBMITTED
def complete(self):
- if self.state == self.states.COMPLETE:
- return True
- return False
+ return self.state == self.states.COMPLETE
class RequestType( object ):
def __init__(self, name=None, desc=None, request_form=None, sample_form=None):
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/model/mapping.py Wed Sep 09 14:24:11 2009 -0400
@@ -233,10 +233,10 @@
Column( "id", Integer, primary_key=True ),
Column( "library_dataset_dataset_association_id", Integer, ForeignKey( "library_dataset_dataset_association.id", use_alter=True, name="library_dataset_dataset_association_id_fk" ), nullable=True, index=True ),#current version of dataset, if null, there is not a current version selected
Column( "folder_id", Integer, ForeignKey( "library_folder.id" ), index=True ),
- Column( "order_id", Integer ),
+ Column( "order_id", Integer ), #not currently being used, but for possible future use
Column( "create_time", DateTime, default=now ),
Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "name", TrimmedString( 255 ), key="_name" ), #when not None/null this will supercede display in library (but not when imported into user's history?)
+ Column( "name", TrimmedString( 255 ), key="_name", index=True ), #when not None/null this will supercede display in library (but not when imported into user's history?)
Column( "info", TrimmedString( 255 ), key="_info" ), #when not None/null this will supercede display in library (but not when imported into user's history?)
Column( "deleted", Boolean, index=True, default=False ) )
@@ -248,7 +248,7 @@
Column( "update_time", DateTime, default=now, onupdate=now ),
Column( "copied_from_history_dataset_association_id", Integer, ForeignKey( "history_dataset_association.id", use_alter=True, name='history_dataset_association_dataset_id_fkey' ), nullable=True ),
Column( "copied_from_library_dataset_dataset_association_id", Integer, ForeignKey( "library_dataset_dataset_association.id", use_alter=True, name='library_dataset_dataset_association_id_fkey' ), nullable=True ),
- Column( "name", TrimmedString( 255 ) ),
+ Column( "name", TrimmedString( 255 ), index=True ),
Column( "info", TrimmedString( 255 ) ),
Column( "blurb", TrimmedString( 255 ) ),
Column( "peek" , TEXT ),
@@ -276,9 +276,9 @@
Column( "parent_id", Integer, ForeignKey( "library_folder.id" ), nullable = True, index=True ),
Column( "create_time", DateTime, default=now ),
Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "name", TEXT ),
+ Column( "name", TEXT, index=True ),
Column( "description", TEXT ),
- Column( "order_id", Integer ),
+ Column( "order_id", Integer ), #not currently being used, but for possible future use
Column( "item_count", Integer ),
Column( "deleted", Boolean, index=True, default=False ),
Column( "purged", Boolean, index=True, default=False ),
@@ -823,15 +823,16 @@
folders=relation(
LibraryFolder,
primaryjoin=( LibraryFolder.table.c.parent_id == LibraryFolder.table.c.id ),
+ order_by=asc( LibraryFolder.table.c.name ),
backref=backref( "parent", primaryjoin=( LibraryFolder.table.c.parent_id == LibraryFolder.table.c.id ), remote_side=[LibraryFolder.table.c.id] ) ),
active_folders=relation( LibraryFolder,
primaryjoin=( ( LibraryFolder.table.c.parent_id == LibraryFolder.table.c.id ) & ( not_( LibraryFolder.table.c.deleted ) ) ),
- order_by=asc( LibraryFolder.table.c.order_id ),
+ order_by=asc( LibraryFolder.table.c.name ),
lazy=True, #"""sqlalchemy.exceptions.ArgumentError: Error creating eager relationship 'active_folders' on parent class '<class 'galaxy.model.LibraryFolder'>' to child class '<class 'galaxy.model.LibraryFolder'>': Cant use eager loading on a self referential relationship."""
viewonly=True ),
datasets=relation( LibraryDataset,
primaryjoin=( ( LibraryDataset.table.c.folder_id == LibraryFolder.table.c.id ) ),
- order_by=asc( LibraryDataset.table.c.order_id ),
+ order_by=asc( LibraryDataset.table.c._name ),
lazy=False,
viewonly=True )
) )
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/model/migrate/versions/0017_library_item_indexes.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/model/migrate/versions/0017_library_item_indexes.py Wed Sep 09 14:24:11 2009 -0400
@@ -0,0 +1,53 @@
+"""
+This script adds 3 indexes to table columns: library_folder.name,
+library_dataset.name, library_dataset_dataset_association.name.
+"""
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+import sys, logging
+
+log = logging.getLogger( __name__ )
+log.setLevel(logging.DEBUG)
+handler = logging.StreamHandler( sys.stdout )
+format = "%(name)s %(levelname)s %(asctime)s %(message)s"
+formatter = logging.Formatter( format )
+handler.setFormatter( formatter )
+log.addHandler( handler )
+
+metadata = MetaData( migrate_engine )
+db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, transactional=False ) )
+LibraryFolder_table = Table( "library_folder", metadata, autoload=True )
+LibraryDatasetDatasetAssociation_table = Table( "library_dataset_dataset_association", metadata, autoload=True )
+LibraryDataset_table = Table( "library_dataset", metadata, autoload=True )
+
+def display_migration_details():
+ print "========================================"
+ print "This script adds 3 indexes to table columns: library_folder.name,"
+ print "library_dataset.name, library_dataset_dataset_association.name."
+ print "========================================"
+
+def upgrade():
+ display_migration_details()
+ # Load existing tables
+ metadata.reflect()
+ # Add 1 index to the library_folder table
+ i = Index( 'ix_library_folder_name', LibraryFolder_table.c.name )
+ try:
+ i.create()
+ except Exception, e:
+ log.debug( "Adding index 'ix_library_folder_name' to library_folder table failed: %s" % ( str( e ) ) )
+ # Add 1 index to the library_dataset_dataset_association table
+ i = Index( 'ix_library_dataset_dataset_association_name', LibraryDatasetDatasetAssociation_table.c.name )
+ try:
+ i.create()
+ except Exception, e:
+ log.debug( "Adding index 'ix_library_dataset_dataset_association_name' to library_dataset_dataset_association table failed: %s" % ( str( e ) ) )
+ # Add 1 index to the library_dataset table
+ i = Index( 'ix_library_dataset_name', LibraryDataset_table.c.name )
+ try:
+ i.create()
+ except Exception, e:
+ log.debug( "Adding index 'ix_library_dataset_name' to library_dataset table failed: %s" % ( str( e ) ) )
+def downgrade():
+ log.debug( "Downgrade is not possible." )
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/security/__init__.py
--- a/lib/galaxy/security/__init__.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/security/__init__.py Wed Sep 09 14:24:11 2009 -0400
@@ -33,11 +33,19 @@
def get_actions( self ):
"""Get all permitted actions as a list of Action objects"""
return self.permitted_actions.__dict__.values()
- def allow_action( self, user, roles, action, **kwd ):
- raise 'No valid method of checking action (%s) on %s for user %s.' % ( action, kwd, user )
def get_item_action( self, action, item ):
raise 'No valid method of retrieving action (%s) for item %s.' % ( action, item )
def guess_derived_permissions_for_datasets( self, datasets = [] ):
+ raise "Unimplemented Method"
+ def can_access_dataset( self, roles, dataset ):
+ raise "Unimplemented Method"
+ def can_manage_dataset( self, roles, dataset ):
+ raise "Unimplemented Method"
+ def can_add_library_item( self, user, roles, item ):
+ raise "Unimplemented Method"
+ def can_modify_library_item( self, user, roles, item ):
+ raise "Unimplemented Method"
+ def can_manage_library_item( self, user, roles, item ):
raise "Unimplemented Method"
def associate_components( self, **kwd ):
raise 'No valid method of associating provided components: %s' % kwd
@@ -89,62 +97,44 @@
to allow migration toward a more SQLAlchemy 0.4 style of use.
"""
return self.model.context.current
- def allow_action( self, user, roles, action, **kwd ):
- if 'dataset' in kwd:
- return self.allow_dataset_action( user, roles, action, kwd[ 'dataset' ] )
- elif 'library_item' in kwd:
- return self.allow_library_item_action( user, roles, action, kwd[ 'library_item' ] )
- raise 'No valid method of checking action (%s) for user %s using kwd %s' % ( action, str( user ), str( kwd ) )
- def allow_dataset_action( self, user, roles, action, dataset ):
- """Returns true when user has permission to perform an action"""
- if not user:
- if action == self.permitted_actions.DATASET_ACCESS and action.action not in [ dp.action for dp in dataset.actions ]:
- # anons only get access, and only if there are no roles required for the access action
- # Other actions (or if the dataset has roles defined for the access action) fall through
- # to the false below
- return True
- elif action.action not in [ dp.action for dp in dataset.actions ]:
- if action.model == 'restrict':
- # Implicit access to restrict-style actions if the dataset does not have the action
- # Grant style actions fall through to the false below
- return True
- else:
- perms = self.get_dataset_permissions( dataset )
- if action in perms.keys():
- # The filter() returns a list of the dataset's role ids of which the user is not a member,
- # so an empty list means the user has all of the required roles.
- if not filter( lambda x: x not in roles, [ r for r in perms[ action ] ] ):
- # User has all of the roles required to perform the action
- return True
- # The user is missing at least one required role
- return False
- def allow_library_item_action( self, user, roles, action, library_item ):
+ def allow_dataset_action( self, roles, action, dataset ):
+ """
+ Returns true when user has permission to perform an action on an
+ instance of Dataset.
+ """
+ dataset_action = self.get_item_action( action, dataset )
+ if dataset_action is None:
+ return action.model == 'restrict'
+ return dataset_action.role in roles
+ def can_access_dataset( self, roles, dataset ):
+ return self.allow_dataset_action( roles, self.permitted_actions.DATASET_ACCESS, dataset )
+ def can_manage_dataset( self, roles, dataset ):
+ return self.allow_dataset_action( roles, self.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset )
+ def allow_library_item_action( self, user, roles, action, item ):
+ """
+ Method for checking a permission for the current user to perform a
+ specific library action on a library item, which must be one of:
+ Library, LibraryFolder, LibraryDataset, LibraryDatasetDatasetAssociation
+ """
if user is None:
# All permissions are granted, so non-users cannot have permissions
return False
- if action.model == 'grant':
- # Check to see if user has access to any of the roles
- allowed_role_assocs = []
- for item_class, permission_class in self.library_item_assocs:
- if isinstance( library_item, item_class ):
- if permission_class == self.model.LibraryPermissions:
- allowed_role_assocs = permission_class.filter_by( action=action.action, library_id=library_item.id ).all()
- elif permission_class == self.model.LibraryFolderPermissions:
- allowed_role_assocs = permission_class.filter_by( action=action.action, library_folder_id=library_item.id ).all()
- elif permission_class == self.model.LibraryDatasetPermissions:
- allowed_role_assocs = permission_class.filter_by( action=action.action, library_dataset_id=library_item.id ).all()
- elif permission_class == self.model.LibraryDatasetDatasetAssociationPermissions:
- allowed_role_assocs = permission_class.filter_by( action=action.action, library_dataset_dataset_association_id=library_item.id ).all()
- for allowed_role_assoc in allowed_role_assocs:
- if allowed_role_assoc.role in roles:
- return True
+ # Check to see if user has access to any of the roles associated with action
+ item_action = self.get_item_action( action, item )
+ if item_action is None:
+ # All permissions are granted, so item must have action
return False
- else:
- raise 'Unimplemented model (%s) specified for action (%s)' % ( action.model, action.action )
+ return item_action.role in roles
+ def can_add_library_item( self, user, roles, item ):
+ return self.allow_library_item_action( user, roles, self.permitted_actions.LIBRARY_ADD, item )
+ def can_modify_library_item( self, user, roles, item ):
+ return self.allow_library_item_action( user, roles, self.permitted_actions.LIBRARY_MODIFY, item )
+ def can_manage_library_item( self, user, roles, item ):
+ return self.allow_library_item_action( user, roles, self.permitted_actions.LIBRARY_MANAGE, item )
def get_item_action( self, action, item ):
# item must be one of: Dataset, Library, LibraryFolder, LibraryDataset, LibraryDatasetDatasetAssociation
for permission in item.actions:
- if permission.action == action:
+ if permission.action == action.action:
return permission
return None
def guess_derived_permissions_for_datasets( self, datasets=[] ):
@@ -276,10 +266,7 @@
if [ assoc for assoc in dataset.history_associations if assoc.history not in user.histories ]:
# Don't change permissions on a dataset associated with a history not owned by the user
continue
- if bypass_manage_permission or self.allow_action( user,
- user.all_roles(),
- self.permitted_actions.DATASET_MANAGE_PERMISSIONS,
- dataset=dataset ):
+ if bypass_manage_permission or self.can_manage_dataset( user.all_roles(), dataset ):
self.set_all_dataset_permissions( dataset, permissions )
def history_get_default_permissions( self, history ):
permissions = {}
@@ -291,7 +278,10 @@
permissions[ action ] = [ dhp.role ]
return permissions
def set_all_dataset_permissions( self, dataset, permissions={} ):
- # Set new permissions on a dataset, eliminating all current permissions
+ """
+ Set new permissions on a dataset, eliminating all current permissions
+ permissions looks like: { Action : [ Role, Role ] }
+ """
# Delete all of the current permissions on the dataset
# TODO: If setting ACCESS permission, at least 1 user must have every role associated with this dataset,
# or the dataset is inaccessible. See admin/library_dataset_dataset_association()
@@ -305,7 +295,10 @@
for dp in [ self.model.DatasetPermissions( action, dataset, role ) for role in roles ]:
dp.flush()
def set_dataset_permission( self, dataset, permission={} ):
- # Set a specific permission on a dataset, leaving all other current permissions on the dataset alone
+ """
+ Set a specific permission on a dataset, leaving all other current permissions on the dataset alone
+ permissions looks like: { Action : [ Role, Role ] }
+ """
# TODO: If setting ACCESS permission, at least 1 user must have every role associated with this dataset,
# or the dataset is inaccessible. See admin/library_dataset_dataset_association()
for action, roles in permission.items():
@@ -331,8 +324,11 @@
dp.delete()
dp.flush()
def get_dataset_permissions( self, dataset ):
- if not isinstance( dataset, self.model.Dataset ):
- dataset = dataset.dataset
+ """
+ Return a dictionary containing the actions and associated roles on dataset.
+ The dictionary looks like: { Action : [ Role, Role ] }
+ dataset must be an instance of Dataset()
+ """
permissions = {}
for dp in dataset.actions:
action = self.get_action( dp.action )
@@ -423,18 +419,29 @@
else:
raise 'Invalid class (%s) specified for target_library_item (%s)' % \
( target_library_item.__class__, target_library_item.__class__.__name__ )
- def show_library_item( self, user, roles, library_item ):
- if self.allow_action( user, roles, self.permitted_actions.LIBRARY_MODIFY, library_item=library_item ) or \
- self.allow_action( user, roles, self.permitted_actions.LIBRARY_MANAGE, library_item=library_item ) or \
- self.allow_action( user, roles, self.permitted_actions.LIBRARY_ADD, library_item=library_item ):
- return True
+ def show_library_item( self, user, roles, library_item, actions_to_check, hidden_folder_ids='' ):
+ """
+ This method must be sent an instance of Library() or LibraryFolder(). Recursive execution produces a
+ comma-separated string of folder ids whose folders do NOT meet the criteria for showing. Along with
+ the string, True is returned if the current user has permission to perform any 1 of actions_to_check
+ on library_item. Otherwise, cycle through all sub-folders in library_item until one is found that meets
+ this criteria, if it exists.
+ """
+ for action in actions_to_check:
+ if self.allow_library_item_action( user, roles, action, library_item ):
+ return True, hidden_folder_ids
if isinstance( library_item, self.model.Library ):
- return self.show_library_item( user, roles, library_item.root_folder )
- elif isinstance( library_item, self.model.LibraryFolder ):
- for folder in library_item.folders:
- if self.show_library_item( user, roles, folder ):
- return True
- return False
+ return self.show_library_item( user, roles, library_item.root_folder, actions_to_check, hidden_folder_ids=hidden_folder_ids )
+ if isinstance( library_item, self.model.LibraryFolder ):
+ for folder in library_item.active_folders:
+ can_show, hidden_folder_ids = self.show_library_item( user, roles, folder, actions_to_check, hidden_folder_ids=hidden_folder_ids )
+ if can_show:
+ return True, hidden_folder_ids
+ if hidden_folder_ids:
+ hidden_folder_ids = '%s,%d' % ( hidden_folder_ids, folder.id )
+ else:
+ hidden_folder_ids = '%d' % folder.id
+ return False, hidden_folder_ids
def set_entity_user_associations( self, users=[], roles=[], groups=[], delete_existing_assocs=True ):
for user in users:
if delete_existing_assocs:
@@ -482,12 +489,14 @@
if 'role' in kwd:
return self.model.GroupRoleAssociation.filter_by( role_id = kwd['role'].id, group_id = kwd['group'].id ).first()
raise 'No valid method of associating provided components: %s' % kwd
- def check_folder_contents( self, user, roles, folder ):
+ def check_folder_contents( self, user, roles, folder, hidden_folder_ids='' ):
"""
- Return true if there are any datasets under 'folder' that are public or that the
- user has access permission on.
+ This method must always be sent an instance of LibraryFolder(). Recursive execution produces a
+ comma-separated string of folder ids whose folders do NOT meet the criteria for showing. Along
+ with the string, True is returned if the current user has permission to access folder. Otherwise,
+ cycle through all sub-folders in folder until one is found that meets this criteria, if it exists.
"""
- action = self.permitted_actions.DATASET_ACCESS.action
+ action = self.permitted_actions.DATASET_ACCESS
lddas = self.sa_session.query( self.model.LibraryDatasetDatasetAssociation ) \
.join( "library_dataset" ) \
.filter( self.model.LibraryDataset.folder == folder ) \
@@ -498,14 +507,19 @@
ldda_access = self.get_item_action( action, ldda.dataset )
if ldda_access is None:
# Dataset is public
- return True
+ return True, hidden_folder_ids
if ldda_access.role in roles:
# The current user has access permission on the dataset
- return True
+ return True, hidden_folder_ids
for sub_folder in folder.active_folders:
- if self.check_folder_contents( user, roles, sub_folder ):
- return True
- return False
+ can_access, hidden_folder_ids = self.check_folder_contents( user, roles, sub_folder, hidden_folder_ids=hidden_folder_ids )
+ if can_access:
+ return True, hidden_folder_ids
+ if hidden_folder_ids:
+ hidden_folder_ids = '%s,%d' % ( hidden_folder_ids, sub_folder.id )
+ else:
+ hidden_folder_ids = '%d' % sub_folder.id
+ return False, hidden_folder_ids
class HostAgent( RBACAgent ):
"""
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/tools/actions/__init__.py Wed Sep 09 14:24:11 2009 -0400
@@ -48,10 +48,7 @@
assoc.flush()
data = new_data
user, roles = trans.get_user_and_roles()
- if data and not trans.app.security_agent.allow_action( user,
- roles,
- data.permitted_actions.DATASET_ACCESS,
- dataset=data.dataset ):
+ if data and not trans.app.security_agent.can_access_dataset( roles, data.dataset ):
raise "User does not have permission to use a dataset (%s) provided for input." % data.id
return data
if isinstance( input, DataToolParameter ):
@@ -267,10 +264,7 @@
user, roles = trans.get_user_and_roles()
for name, dataset in inp_data.iteritems():
if dataset:
- if not trans.app.security_agent.allow_action( user,
- roles,
- dataset.permitted_actions.DATASET_ACCESS,
- dataset=dataset.dataset ):
+ if not trans.app.security_agent.can_access_dataset( roles, dataset.dataset ):
raise "User does not have permission to use a dataset (%s) provided for input." % data.id
job.add_input_dataset( name, dataset )
else:
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/tools/parameters/basic.py Wed Sep 09 14:24:11 2009 -0400
@@ -1149,19 +1149,11 @@
hid = str( hda.hid )
if not hda.dataset.state in [galaxy.model.Dataset.states.ERROR, galaxy.model.Dataset.states.DISCARDED] and \
hda.visible and \
- trans.app.security_agent.allow_action( user,
- roles,
- hda.permitted_actions.DATASET_ACCESS,
- dataset=hda.dataset ):
+ trans.app.security_agent.can_access_dataset( roles, hda.dataset ):
# If we are sending data to an external application, then we need to make sure there are no roles
- # associated with the dataset that restrict it's access from "public". We determine this by sending
- # None as the user to the allow_action method.
- if self.tool and self.tool.tool_type == 'data_destination':
- if not trans.app.security_agent.allow_action( None,
- None,
- hda.permitted_actions.DATASET_ACCESS,
- dataset=hda.dataset ):
- continue
+ # associated with the dataset that restrict it's access from "public".
+ if self.tool and self.tool.tool_type == 'data_destination' and not trans.app.security_agent.dataset_is_public( hda.dataset ):
+ continue
if self.options and hda.get_dbkey() != filter_value:
continue
if isinstance( hda.datatype, self.formats):
@@ -1172,10 +1164,7 @@
if target_ext:
if converted_dataset:
hda = converted_dataset
- if not trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.DATASET_ACCESS,
- dataset=hda.dataset ):
+ if not trans.app.security_agent.can_access_dataset( roles, hda.dataset ):
continue
selected = ( value and ( hda in value ) )
field.add_option( "%s: (as %s) %s" % ( hid, target_ext, hda_name ), hda.id, selected )
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/tools/util/maf_utilities.py
--- a/lib/galaxy/tools/util/maf_utilities.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/tools/util/maf_utilities.py Wed Sep 09 14:24:11 2009 -0400
@@ -7,10 +7,41 @@
import bx.align.maf
import bx.intervals
import bx.interval_index_file
-import sys, os, string, tempfile
+import sys, os, string, tempfile
+import logging
+from copy import deepcopy
assert sys.version_info[:2] >= ( 2, 4 )
-
+
+log = logging.getLogger(__name__)
+
+
+GAP_CHARS = [ '-' ]
+SRC_SPLIT_CHAR = '.'
+
+def src_split( src ):
+ spec, chrom = bx.align.maf.src_split( src )
+ if None in [ spec, chrom ]:
+ spec = chrom = src
+ return spec, chrom
+
+def src_merge( spec, chrom, contig = None ):
+ if None in [ spec, chrom ]:
+ spec = chrom = spec or chrom
+ return bx.align.maf.src_merge( spec, chrom, contig )
+
+def get_species_in_block( block ):
+ species = []
+ for c in block.components:
+ spec, chrom = src_split( c.src )
+ if spec not in species:
+ species.append( spec )
+ return species
+
+def tool_fail( msg = "Unknown Error" ):
+ print >> sys.stderr, "Fatal Error: %s" % msg
+ sys.exit()
+
#an object corresponding to a reference layered alignment
class RegionAlignment( object ):
@@ -153,69 +184,187 @@
except:
return build_maf_index( maf_file, species = species )
+#*** ANYCHANGE TO THIS METHOD HERE OR IN galaxy.datatypes.sequences MUST BE PROPAGATED ***
+def build_maf_index_species_chromosomes( filename, index_species = None ):
+ species = []
+ species_chromosomes = {}
+ indexes = bx.interval_index_file.Indexes()
+ try:
+ maf_reader = bx.align.maf.Reader( open( filename ) )
+ while True:
+ pos = maf_reader.file.tell()
+ block = maf_reader.next()
+ if block is None: break
+ for c in block.components:
+ spec = c.src
+ chrom = None
+ if "." in spec:
+ spec, chrom = spec.split( ".", 1 )
+ if spec not in species:
+ species.append( spec )
+ species_chromosomes[spec] = []
+ if chrom and chrom not in species_chromosomes[spec]:
+ species_chromosomes[spec].append( chrom )
+ if index_species is None or spec in index_species:
+ forward_strand_start = c.forward_strand_start
+ forward_strand_end = c.forward_strand_end
+ try:
+ forward_strand_start = int( forward_strand_start )
+ forward_strand_end = int( forward_strand_end )
+ except ValueError:
+ continue #start and end are not integers, can't add component to index, goto next component
+ #this likely only occurs when parse_e_rows is True?
+ #could a species exist as only e rows? should the
+ if forward_strand_end > forward_strand_start:
+ #require positive length; i.e. certain lines have start = end = 0 and cannot be indexed
+ indexes.add( c.src, forward_strand_start, forward_strand_end, pos, max=c.src_size )
+ except Exception, e:
+ #most likely a bad MAF
+ log.debug( 'Building MAF index on %s failed: %s' % ( filename, e ) )
+ return ( None, [], {} )
+ return ( indexes, species, species_chromosomes )
#builds and returns ( index, index_filename ) for specified maf_file
def build_maf_index( maf_file, species = None ):
- indexes = bx.interval_index_file.Indexes()
- try:
- maf_reader = bx.align.maf.Reader( open( maf_file ) )
- # Need to be a bit tricky in our iteration here to get the 'tells' right
- while True:
- pos = maf_reader.file.tell()
- block = maf_reader.next()
- if block is None: break
- for c in block.components:
- if species is not None and c.src.split( "." )[0] not in species:
- continue
- indexes.add( c.src, c.forward_strand_start, c.forward_strand_end, pos )
+ indexes, found_species, species_chromosomes = build_maf_index_species_chromosomes( maf_file, species )
+ if indexes is not None:
fd, index_filename = tempfile.mkstemp()
out = os.fdopen( fd, 'w' )
indexes.write( out )
out.close()
- return ( bx.align.maf.Indexed( maf_file, index_filename = index_filename, keep_open = True, parse_e_rows = False ), index_filename )
- except:
- return ( None, None )
-
-def chop_block_by_region( block, src, region, species = None, mincols = 0, force_strand = None ):
- ref = block.get_component_by_src( src )
- #We want our block coordinates to be from positive strand
- if ref.strand == "-":
- block = block.reverse_complement()
- ref = block.get_component_by_src( src )
+ return ( bx.align.maf.Indexed( maf_file, index_filename = index_filename, keep_open = True, parse_e_rows = False ), index_filename )
+ return ( None, None )
+
+def component_overlaps_region( c, region ):
+ if c is None: return False
+ start, end = c.get_forward_strand_start(), c.get_forward_strand_end()
+ if region.start >= end or region.end <= start:
+ return False
+ return True
+
+def chop_block_by_region( block, src, region, species = None, mincols = 0 ):
+ # This chopping method was designed to maintain consistency with how start/end padding gaps have been working in Galaxy thus far:
+ # behavior as seen when forcing blocks to be '+' relative to src sequence (ref) and using block.slice_by_component( ref, slice_start, slice_end )
+ # whether-or-not this is the 'correct' behavior is questionable, but this will at least maintain consistency
+ # comments welcome
+ slice_start = block.text_size #max for the min()
+ slice_end = 0 #min for the max()
+ old_score = block.score #save old score for later use
+ # We no longer assume only one occurance of src per block, so we need to check them all
+ for c in iter_components_by_src( block, src ):
+ if component_overlaps_region( c, region ):
+ if c.text is not None:
+ rev_strand = False
+ if c.strand == "-":
+ #We want our coord_to_col coordinates to be returned from positive stranded component
+ rev_strand = True
+ c = c.reverse_complement()
+ start = max( region.start, c.start )
+ end = min( region.end, c.end )
+ start = c.coord_to_col( start )
+ end = c.coord_to_col( end )
+ if rev_strand:
+ #need to orient slice coordinates to the original block direction
+ slice_len = end - start
+ end = len( c.text ) - start
+ start = end - slice_len
+ slice_start = min( start, slice_start )
+ slice_end = max( end, slice_end )
+
+ if slice_start < slice_end:
+ block = block.slice( slice_start, slice_end )
+ if block.text_size > mincols:
+ # restore old score, may not be accurate, but it is better than 0 for everything?
+ block.score = old_score
+ if species is not None:
+ block = block.limit_to_species( species )
+ block.remove_all_gap_columns()
+ return block
+ return None
- #save old score here for later use
- old_score = block.score
- slice_start = max( region.start, ref.start )
- slice_end = min( region.end, ref.end )
-
- #slice block by reference species at determined limits
- block = block.slice_by_component( ref, slice_start, slice_end )
-
- if block.text_size > mincols:
- if ( force_strand is None and region.strand != ref.strand ) or ( force_strand is not None and force_strand != ref.strand ):
- block = block.reverse_complement()
- # restore old score, may not be accurate, but it is better than 0 for everything
- block.score = old_score
- if species is not None:
- block = block.limit_to_species( species )
- block.remove_all_gap_columns()
- return block
- return None
+def orient_block_by_region( block, src, region, force_strand = None ):
+ #loop through components matching src,
+ #make sure each of these components overlap region
+ #cache strand for each of overlaping regions
+ #if force_strand / region.strand not in strand cache, reverse complement
+ ### we could have 2 sequences with same src, overlapping region, on different strands, this would cause no reverse_complementing
+ strands = [ c.strand for c in iter_components_by_src( block, src ) if component_overlaps_region( c, region ) ]
+ if strands and ( force_strand is None and region.strand not in strands ) or ( force_strand is not None and force_strand not in strands ):
+ block = block.reverse_complement()
+ return block
+
+def get_oriented_chopped_blocks_for_region( index, src, region, species = None, mincols = 0, force_strand = None ):
+ for block, idx, offset in get_oriented_chopped_blocks_with_index_offset_for_region( index, src, region, species, mincols, force_strand ):
+ yield block
+def get_oriented_chopped_blocks_with_index_offset_for_region( index, src, region, species = None, mincols = 0, force_strand = None ):
+ for block, idx, offset in get_chopped_blocks_with_index_offset_for_region( index, src, region, species, mincols ):
+ yield orient_block_by_region( block, src, region, force_strand ), idx, offset
+
+#split a block with multiple occurances of src into one block per src
+def iter_blocks_split_by_src( block, src ):
+ for src_c in iter_components_by_src( block, src ):
+ new_block = bx.align.Alignment( score=block.score, attributes=deepcopy( block.attributes ) )
+ new_block.text_size = block.text_size
+ for c in block.components:
+ if c == src_c or c.src != src:
+ new_block.add_component( deepcopy( c ) ) #components have reference to alignment, dont want to loose reference to original alignment block in original components
+ yield new_block
+
+#split a block into multiple blocks with all combinations of a species appearing only once per block
+def iter_blocks_split_by_species( block, species = None ):
+ def __split_components_by_species( components_by_species, new_block ):
+ if components_by_species:
+ #more species with components to add to this block
+ components_by_species = deepcopy( components_by_species )
+ spec_comps = components_by_species.pop( 0 )
+ for c in spec_comps:
+ newer_block = deepcopy( new_block )
+ newer_block.add_component( deepcopy( c ) )
+ for value in __split_components_by_species( components_by_species, newer_block ):
+ yield value
+ else:
+ #no more components to add, yield this block
+ yield new_block
+
+ #divide components by species
+ spec_dict = {}
+ if not species:
+ species = []
+ for c in block.components:
+ spec, chrom = src_split( c.src )
+ if spec not in spec_dict:
+ spec_dict[ spec ] = []
+ species.append( spec )
+ spec_dict[ spec ].append( c )
+ else:
+ for spec in species:
+ spec_dict[ spec ] = []
+ for c in iter_components_by_src_start( block, spec ):
+ spec_dict[ spec ].append( c )
+
+ empty_block = bx.align.Alignment( score=block.score, attributes=deepcopy( block.attributes ) ) #should we copy attributes?
+ empty_block.text_size = block.text_size
+ #call recursive function to split into each combo of spec/blocks
+ for value in __split_components_by_species( spec_dict.values(), empty_block ):
+ sort_block_components_by_block( value, block ) #restore original component order
+ yield value
+
+
#generator yielding only chopped and valid blocks for a specified region
-def get_chopped_blocks_for_region( index, src, region, species = None, mincols = 0, force_strand = None ):
- for block, idx, offset in get_chopped_blocks_with_index_offset_for_region( index, src, region, species, mincols, force_strand ):
+def get_chopped_blocks_for_region( index, src, region, species = None, mincols = 0 ):
+ for block, idx, offset in get_chopped_blocks_with_index_offset_for_region( index, src, region, species, mincols ):
yield block
-def get_chopped_blocks_with_index_offset_for_region( index, src, region, species = None, mincols = 0, force_strand = None ):
+def get_chopped_blocks_with_index_offset_for_region( index, src, region, species = None, mincols = 0 ):
for block, idx, offset in index.get_as_iterator_with_index_and_offset( src, region.start, region.end ):
- block = chop_block_by_region( block, src, region, species, mincols, force_strand )
+ block = chop_block_by_region( block, src, region, species, mincols )
if block is not None:
yield block, idx, offset
#returns a filled region alignment for specified regions
-def get_region_alignment( index, primary_species, chrom, start, end, strand = '+', species = None, mincols = 0 ):
+def get_region_alignment( index, primary_species, chrom, start, end, strand = '+', species = None, mincols = 0, overwrite_with_gaps = True ):
if species is not None: alignment = RegionAlignment( end - start, species )
else: alignment = RegionAlignment( end - start, primary_species )
- return fill_region_alignment( alignment, index, primary_species, chrom, start, end, strand, species, mincols )
+ return fill_region_alignment( alignment, index, primary_species, chrom, start, end, strand, species, mincols, overwrite_with_gaps )
#reduces a block to only positions exisiting in the src provided
def reduce_block_by_primary_genome( block, species, chromosome, region_start ):
@@ -237,13 +386,11 @@
return ( start_offset, species_texts )
#fills a region alignment
-def fill_region_alignment( alignment, index, primary_species, chrom, start, end, strand = '+', species = None, mincols = 0 ):
+def fill_region_alignment( alignment, index, primary_species, chrom, start, end, strand = '+', species = None, mincols = 0, overwrite_with_gaps = True ):
region = bx.intervals.Interval( start, end )
region.chrom = chrom
region.strand = strand
primary_src = "%s.%s" % ( primary_species, chrom )
-
-
#Order blocks overlaping this position by score, lowest first
blocks = []
@@ -255,28 +402,40 @@
break
else:
blocks.append( ( score, idx, offset ) )
-
+
+ gap_chars_tuple = tuple( GAP_CHARS )
+ gap_chars_str = ''.join( GAP_CHARS )
#Loop through ordered blocks and layer by increasing score
- for block_dict in blocks:
- block = chop_block_by_region( block_dict[1].get_at_offset( block_dict[2] ), primary_src, region, species, mincols, strand )
- if block is None: continue
- start_offset, species_texts = reduce_block_by_primary_genome( block, primary_species, chrom, start )
- for spec, text in species_texts.items():
- try:
- alignment.set_range( start_offset, spec, text )
- except:
- #species/sequence for species does not exist
- pass
-
+ for block_dict in blocks:
for block in iter_blocks_split_by_species( block_dict[1].get_at_offset( block_dict[2] ) ): #need to handle each occurance of sequence in block seperately
+ if component_overlaps_region( block.get_component_by_src( primary_src ), region ):
+ block = chop_block_by_region( block, primary_src, region, species, mincols ) #chop block
+ block = orient_block_by_region( block, primary_src, region ) #orient block
+ start_offset, species_texts = reduce_block_by_primary_genome( block, primary_species, chrom, start )
+ for spec, text in species_texts.items():
+ #we should trim gaps from both sides, since these are not positions in this species genome (sequence)
+ text = text.rstrip( gap_chars_str )
+ gap_offset = 0
+ while text.startswith( gap_chars_tuple ):
+ gap_offset += 1
+ text = text[1:]
+ if not text:
+ break
+ if text:
+ if overwrite_with_gaps:
+ alignment.set_range( start_offset + gap_offset, spec, text )
+ else:
+ for i, char in enumerate( text ):
+ if char not in GAP_CHARS:
+ alignment.set_position( start_offset + gap_offset + i, spec, char )
return alignment
#returns a filled spliced region alignment for specified region with start and end lists
-def get_spliced_region_alignment( index, primary_species, chrom, starts, ends, strand = '+', species = None, mincols = 0 ):
+def get_spliced_region_alignment( index, primary_species, chrom, starts, ends, strand = '+', species = None, mincols = 0, overwrite_with_gaps = True ):
#create spliced alignment object
if species is not None: alignment = SplicedAlignment( starts, ends, species )
else: alignment = SplicedAlignment( starts, ends, [primary_species] )
for exon in alignment.exons:
- fill_region_alignment( exon, index, primary_species, chrom, exon.start, exon.end, strand, species, mincols)
+ fill_region_alignment( exon, index, primary_species, chrom, exon.start, exon.end, strand, species, mincols, overwrite_with_gaps )
return alignment
#loop through string array, only return non-commented lines
@@ -319,29 +478,36 @@
starts.append( start )
ends.append( end )
return ( starts, ends, fields )
-
-def get_species_in_maf( maf_filename ):
- try:
- species={}
-
- file_in = open( maf_filename, 'r' )
- maf_reader = maf.Reader( file_in )
-
- for i, m in enumerate( maf_reader ):
- l = m.components
- for c in l:
- spec, chrom = maf.src_split( c.src )
- if not spec or not chrom:
- spec = chrom = c.src
- species[spec] = spec
-
- file_in.close()
-
- species = species.keys()
- species.sort()
- return species
- except:
- return []
+
+def iter_components_by_src( block, src ):
+ for c in block.components:
+ if c.src == src:
+ yield c
+
+def get_components_by_src( block, src ):
+ return [ value for value in iter_components_by_src( block, src ) ]
+
+def iter_components_by_src_start( block, src ):
+ for c in block.components:
+ if c.src.startswith( src ):
+ yield c
+
+def get_components_by_src_start( block, src ):
+ return [ value for value in iter_components_by_src_start( block, src ) ]
+
+def sort_block_components_by_block( block1, block2 ):
+ #orders the components in block1 by the index of the component in block2
+ #block1 must be a subset of block2
+ #occurs in-place
+ return block1.components.sort( cmp = lambda x, y: block2.components.index( x ) - block2.components.index( y ) )
+
+def get_species_in_maf( maf_filename ):
+ species = []
+ for block in maf.Reader( open( maf_filename ) ):
+ for spec in get_species_in_block( block ):
+ if spec not in species:
+ species.append( spec )
+ return species
def parse_species_option( species ):
if species:
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/web/controllers/admin.py
--- a/lib/galaxy/web/controllers/admin.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/web/controllers/admin.py Wed Sep 09 14:24:11 2009 -0400
@@ -2001,7 +2001,6 @@
show_deleted=False,
msg=msg,
messagetype=messagetype )
-
def _save_request_type(self, trans, **kwd):
params = util.Params( kwd )
num_states = int( util.restore_text( params.get( 'num_states', 0 ) ))
@@ -2031,7 +2030,6 @@
ss.flush()
msg = "The new request type named '%s' with %s state(s) has been created" % (rt.name, num_states)
return rt, msg
-
@web.expose
@web.require_admin
def delete_request_type( self, trans, **kwd ):
@@ -2045,7 +2043,6 @@
action='manage_request_types',
msg='Request type <b>%s</b> has been deleted' % rt.name,
messagetype='done') )
-
@web.expose
@web.require_admin
def undelete_request_type( self, trans, **kwd ):
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/web/controllers/dataset.py
--- a/lib/galaxy/web/controllers/dataset.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/web/controllers/dataset.py Wed Sep 09 14:24:11 2009 -0400
@@ -109,10 +109,7 @@
if not data:
raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( dataset_id ) )
user, roles = trans.get_user_and_roles()
- if trans.app.security_agent.allow_action( user,
- roles,
- data.permitted_actions.DATASET_ACCESS,
- dataset=data.dataset ):
+ if trans.app.security_agent.can_access_dataset( roles, data.dataset ):
if data.state == trans.model.Dataset.states.UPLOAD:
return trans.show_error_message( "Please wait until this dataset finishes uploading before attempting to view it." )
if filename is None or filename.lower() == "index":
@@ -147,12 +144,9 @@
return trans.show_error_message( 'Invalid parameters specified for "display at" link, please contact a Galaxy administrator' )
redirect_url = kwd['redirect_url'] % urllib.quote_plus( kwd['display_url'] )
user, roles = trans.get_user_and_roles()
- if trans.app.security_agent.allow_action( None, None, data.permitted_actions.DATASET_ACCESS, dataset=data.dataset ):
+ if trans.app.security_agent.dataset_is_public( data.dataset ):
return trans.response.send_redirect( redirect_url ) # anon access already permitted by rbac
- if trans.app.security_agent.allow_action( user,
- roles,
- data.permitted_actions.DATASET_ACCESS,
- dataset=data.dataset ):
+ if trans.app.security_agent.can_access_dataset( roles, data.dataset ):
trans.app.host_security_agent.set_dataset_permissions( data, trans.user, site )
return trans.response.send_redirect( redirect_url )
else:
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/web/controllers/history.py
--- a/lib/galaxy/web/controllers/history.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/web/controllers/history.py Wed Sep 09 14:24:11 2009 -0400
@@ -443,15 +443,9 @@
for hda in history.activatable_datasets:
# If the current dataset is not public, we may need to perform an action on it to
# make it accessible by the other user.
- if not trans.app.security_agent.allow_action( send_to_user,
- send_to_user.all_roles(),
- trans.app.security_agent.permitted_actions.DATASET_ACCESS,
- dataset=hda.dataset ):
+ if not trans.app.security_agent.can_access_dataset( send_to_user.all_roles(), hda.dataset ):
# The user with which we are sharing the history does not have access permission on the current dataset
- if trans.app.security_agent.allow_action( user,
- user_roles,
- trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS,
- dataset=hda.dataset ) and not hda.dataset.library_associations:
+ if trans.app.security_agent.can_manage_dataset( user_roles, hda.dataset ) and not hda.dataset.library_associations:
# The current user has authority to change permissions on the current dataset because
# they have permission to manage permissions on the dataset and the dataset is not associated
# with a library.
@@ -556,15 +550,9 @@
no_change_needed[ send_to_user ][ history ] = [ hda ]
else:
no_change_needed[ send_to_user ][ history ].append( hda )
- elif not trans.app.security_agent.allow_action( send_to_user,
- send_to_user.all_roles(),
- trans.app.security_agent.permitted_actions.DATASET_ACCESS,
- dataset=hda.dataset ):
+ elif not trans.app.security_agent.can_access_dataset( send_to_user.all_roles(), hda.dataset ):
# The user with which we are sharing the history does not have access permission on the current dataset
- if trans.app.security_agent.allow_action( user,
- user_roles,
- trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS,
- dataset=hda.dataset ) and not hda.dataset.library_associations:
+ if trans.app.security_agent.can_manage_dataset( user_roles, hda.dataset ) and not hda.dataset.library_associations:
# The current user has authority to change permissions on the current dataset because
# they have permission to manage permissions on the dataset and the dataset is not associated
# with a library.
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/web/controllers/library.py
--- a/lib/galaxy/web/controllers/library.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/web/controllers/library.py Wed Sep 09 14:24:11 2009 -0400
@@ -2,6 +2,7 @@
from galaxy.model.orm import *
from galaxy.datatypes import sniff
from galaxy import util
+from galaxy.util.odict import odict
from galaxy.web.controllers.forms import get_all_forms, get_form_widgets
from galaxy.util.streamball import StreamBall
import logging, tempfile, zipfile, tarfile, os, sys
@@ -65,23 +66,24 @@
user, roles = trans.get_user_and_roles()
all_libraries = trans.app.model.Library.filter( trans.app.model.Library.table.c.deleted==False ) \
.order_by( trans.app.model.Library.name ).all()
- authorized_libraries = []
+ library_actions = [ trans.app.security_agent.permitted_actions.LIBRARY_ADD,
+ trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
+ trans.app.security_agent.permitted_actions.LIBRARY_MANAGE ]
+ # The authorized_libraries dictionary looks like: { library : '1,2' }, library : '3' }
+ # Its keys are the libraries that should be displayed for the current user and whose values are a
+ # string of comma-separated folder ids, of the associated folders the should NOT be displayed.
+ # The folders that should not be displayed may not be a complete list, but it is ultimately passed
+ # to the browse_library() method and the browse_library.mako template to keep from re-checking the
+ # same folders when the library is rendered.
+ authorized_libraries = odict()
for library in all_libraries:
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_ADD,
- library_item=library ) or \
- trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
- library_item=library ) or \
- trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
- library_item=library ) or \
- trans.app.security_agent.check_folder_contents( user, roles, library.root_folder ) or \
- trans.app.security_agent.show_library_item( user, roles, library ):
- authorized_libraries.append( library )
+ can_access, hidden_folder_ids = trans.app.security_agent.check_folder_contents( user, roles, library.root_folder )
+ if can_access:
+ authorized_libraries[ library ] = hidden_folder_ids
+ else:
+ can_show, hidden_folder_ids = trans.app.security_agent.show_library_item( user, roles, library, library_actions )
+ if can_show:
+ authorized_libraries[ library ] = hidden_folder_ids
return trans.fill_template( '/library/browse_libraries.mako',
libraries=authorized_libraries,
default_action=params.get( 'default_action', None ),
@@ -94,6 +96,7 @@
messagetype = params.get( 'messagetype', 'done' )
id = params.get( 'id', None )
if not id:
+ # To handle bots
msg = "You must specify a library id."
return trans.response.send_redirect( web.url_for( controller='library',
action='browse_libraries',
@@ -102,6 +105,7 @@
messagetype='error' ) )
library = library=trans.app.model.Library.get( id )
if not library:
+ # To handle bots
msg = "Invalid library id ( %s )."
return trans.response.send_redirect( web.url_for( controller='library',
action='browse_libraries',
@@ -109,9 +113,11 @@
msg=util.sanitize_text( msg ),
messagetype='error' ) )
created_ldda_ids = params.get( 'created_ldda_ids', '' )
+ hidden_folder_ids = util.listify( util.restore_text( params.get( 'hidden_folder_ids', '' ) ) )
return trans.fill_template( '/library/browse_library.mako',
library=trans.app.model.Library.get( id ),
created_ldda_ids=created_ldda_ids,
+ hidden_folder_ids=hidden_folder_ids,
default_action=params.get( 'default_action', None ),
comptypes=comptypes,
msg=msg,
@@ -278,10 +284,7 @@
user, roles = trans.get_user_and_roles()
for id in ldda_ids:
ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( id )
- if not ldda or not trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.DATASET_ACCESS,
- dataset = ldda.dataset ):
+ if not ldda or not trans.app.security_agent.can_access_dataset( roles, ldda.dataset ):
continue
path = ""
parent_folder = ldda.library_dataset.folder
@@ -379,10 +382,7 @@
user, roles = trans.get_user_and_roles()
if action == 'information':
if params.get( 'edit_attributes_button', False ):
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
- library_item=library_dataset ):
+ if trans.app.security_agent.can_modify_library_item( user, roles, library_dataset ):
if params.get( 'edit_attributes_button', False ):
old_name = library_dataset.name
new_name = util.restore_text( params.get( 'name', '' ) )
@@ -406,10 +406,7 @@
messagetype=messagetype )
elif action == 'permissions':
if params.get( 'update_roles_button', False ):
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
- library_item=library_dataset ):
+ if trans.app.security_agent.can_manage_library_item( user, roles, library_dataset ):
# The user clicked the Save button on the 'Associate With Roles' form
permissions = {}
for k, v in trans.app.model.Library.permitted_actions.items():
@@ -496,14 +493,8 @@
if action == 'permissions':
if params.get( 'update_roles_button', False ):
# The user clicked the Save button on the 'Associate With Roles' form
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
- library_item=ldda ) and \
- trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS,
- dataset=ldda.dataset ):
+ if trans.app.security_agent.can_manage_library_item( user, roles, ldda ) and \
+ trans.app.security_agent.can_manage_dataset( roles, ldda.dataset ):
permissions = {}
for k, v in trans.app.model.Dataset.permitted_actions.items():
in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( params.get( k + '_in', [] ) ) ]
@@ -542,10 +533,7 @@
elif action == 'edit_info':
if params.get( 'change', False ):
# The user clicked the Save button on the 'Change data type' form
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
- library_item=ldda ):
+ if trans.app.security_agent.can_modify_library_item( user, roles, ldda ):
if ldda.datatype.allow_datatype_change and trans.app.datatypes_registry.get_datatype_by_extension( params.datatype ).allow_datatype_change:
trans.app.datatypes_registry.change_datatype( ldda, params.datatype )
trans.app.model.flush()
@@ -566,10 +554,7 @@
messagetype=messagetype )
elif params.get( 'save', False ):
# The user clicked the Save button on the 'Edit Attributes' form
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
- library_item=ldda ):
+ if trans.app.security_agent.can_modify_library_item( user, roles, ldda ):
old_name = ldda.name
new_name = util.restore_text( params.get( 'name', '' ) )
new_info = util.restore_text( params.get( 'info', '' ) )
@@ -608,10 +593,7 @@
messagetype=messagetype )
elif params.get( 'detect', False ):
# The user clicked the Auto-detect button on the 'Edit Attributes' form
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
- library_item=ldda ):
+ if trans.app.security_agent.can_modify_library_item( user, roles, ldda ):
for name, spec in ldda.datatype.metadata_spec.items():
# We need to be careful about the attributes we are resetting
if name not in [ 'name', 'info', 'dbkey' ]:
@@ -633,10 +615,7 @@
msg=msg,
messagetype=messagetype )
elif params.get( 'delete', False ):
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
- library_item=folder ):
+ if trans.app.security_agent.can_modify_library_item( user, roles, folder ):
ldda.deleted = True
ldda.flush()
msg = 'Dataset %s has been removed from this library' % ldda.name
@@ -651,10 +630,7 @@
widgets=widgets,
msg=msg,
messagetype=messagetype )
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
- library_item=ldda ):
+ if trans.app.security_agent.can_modify_library_item( user, roles, ldda ):
ldda.datatype.before_edit( ldda )
if "dbkey" in ldda.datatype.metadata_spec and not ldda.metadata.dbkey:
# Copy dbkey into metadata, for backwards compatability
@@ -692,14 +668,8 @@
messagetype='error' ) )
if action == 'permissions':
if params.get( 'update_roles_button', False ):
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
- library_item=ldda ) and \
- trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS,
- dataset=ldda.dataset ):
+ if trans.app.security_agent.can_manage_library_item( user, roles, ldda ) and \
+ trans.app.security_agent.can_manage_dataset( roles, ldda.dataset ):
permissions = {}
for k, v in trans.app.model.Dataset.permitted_actions.items():
in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( params.get( k + '_in', [] ) ) ]
@@ -730,14 +700,8 @@
library_id=library_id,
msg=msg,
messagetype=messagetype )
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
- library_item=ldda ) and \
- trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS,
- dataset=ldda.dataset ):
+ if trans.app.security_agent.can_manage_library_item( user, roles, ldda ) and \
+ trans.app.security_agent.can_manage_dataset( roles, ldda.dataset ):
# Ensure that the permissions across all library items are identical, otherwise we can't update them together.
check_list = []
for ldda in lddas:
@@ -769,14 +733,8 @@
library_id=library_id,
msg=msg,
messagetype=messagetype )
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_ADD,
- library_item=folder ) or \
- ( replace_dataset and trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
- library_item=replace_dataset ) ):
+ if trans.app.security_agent.can_add_library_item( user, roles, folder ) or \
+ ( replace_dataset and trans.app.security_agent.can_modify_library_item( user, roles, replace_dataset ) ):
if params.get( 'new_dataset_button', False ):
upload_option = params.get( 'upload_option', 'upload_file' )
created_ldda_ids = trans.webapp.controllers[ 'library_dataset' ].upload_dataset( trans,
@@ -799,10 +757,7 @@
# Since permissions on all LibraryDatasetDatasetAssociations must be the same at this point, we only need
# to check one of them to see if the current user can manage permissions on them.
check_ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( ldda_id_list[0] )
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
- library_item=check_ldda ):
+ if trans.app.security_agent.can_manage_library_item( user, roles, check_ldda ):
if replace_dataset:
default_action = ''
else:
@@ -924,10 +879,7 @@
# to check one of them to see if the current user can manage permissions on them.
check_ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( ldda_id_list[0] )
user, roles = trans.get_user_and_roles()
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
- library_item=check_ldda ):
+ if trans.app.security_agent.can_manage_library_item( user, roles, check_ldda ):
if replace_dataset:
default_action = ''
else:
@@ -1028,10 +980,7 @@
else:
widgets = []
if params.get( 'rename_folder_button', False ):
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
- library_item=folder ):
+ if trans.app.security_agent.can_modify_library_item( user, roles, folder ):
old_name = folder.name
new_name = util.restore_text( params.name )
new_description = util.restore_text( params.description )
@@ -1072,10 +1021,7 @@
elif action == 'permissions':
if params.get( 'update_roles_button', False ):
# The user clicked the Save button on the 'Associate With Roles' form
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
- library_item=folder ):
+ if trans.app.security_agent.can_manage_library_item( user, roles, folder ):
permissions = {}
for k, v in trans.app.model.Library.permitted_actions.items():
in_roles = [ trans.app.model.Role.get( int( x ) ) for x in util.listify( params.get( k + '_in', [] ) ) ]
@@ -1198,24 +1144,40 @@
msg=util.sanitize_text( msg ),
messagetype='done' ) )
-def get_authorized_libs( trans, user ):
- # TODO: this is a mis-named function - the name should reflect the authorization policy
- # If user is not authenticated, this method should not even be called. Also, it looks
- # like all that is using this is the new request stuff, so it should be placed there.
- if not user:
- return []
- roles = user.all_roles()
- all_libraries = trans.app.model.Library.filter( trans.app.model.Library.table.c.deleted == False ) \
- .order_by( trans.app.model.Library.name ).all()
- authorized_libraries = []
- for library in all_libraries:
- if trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_ADD,
- library_item=library ) \
- or trans.app.security_agent.allow_action( user,
- roles,
- trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
- library_item=library ):
- authorized_libraries.append( library )
- return authorized_libraries
+# ---- Utility methods -------------------------------------------------------
+
+def active_folders( trans, folder ):
+ # Much faster way of retrieving all active sub-folders within a given folder than the
+ # performance of the mapper. This query also eagerloads the permissions on each folder.
+ return trans.sa_session.query( trans.app.model.LibraryFolder ) \
+ .filter_by( parent=folder, deleted=False ) \
+ .options( eagerload_all( "actions" ) ) \
+ .order_by( trans.app.model.LibraryFolder.table.c.name ) \
+ .all()
+def activatable_folders( trans, folder ):
+ return trans.sa_session.query( trans.app.model.LibraryFolder ) \
+ .filter_by( parent=folder, purged=False ) \
+ .options( eagerload_all( "actions" ) ) \
+ .order_by( trans.app.model.LibraryFolder.table.c.name ) \
+ .all()
+def active_folders_and_lddas( trans, folder ):
+ folders = active_folders( trans, folder )
+ # This query is much faster than the folder.active_library_datasets property
+ lddas = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ) \
+ .filter_by( deleted=False ) \
+ .join( "library_dataset" ) \
+ .filter( trans.app.model.LibraryDataset.table.c.folder_id==folder.id ) \
+ .order_by( trans.app.model.LibraryDatasetDatasetAssociation.table.c.name ) \
+ .all()
+ return folders, lddas
+def activatable_folders_and_lddas( trans, folder ):
+ folders = activatable_folders( trans, folder )
+ # This query is much faster than the folder.activatable_library_datasets property
+ lddas = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ) \
+ .join( "library_dataset" ) \
+ .filter( trans.app.model.LibraryDataset.table.c.folder_id==folder.id ) \
+ .join( "dataset" ) \
+ .filter( trans.app.model.Dataset.table.c.deleted==False ) \
+ .order_by( trans.app.model.LibraryDatasetDatasetAssociation.table.c.name ) \
+ .all()
+ return folders, lddas
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/web/controllers/requests.py
--- a/lib/galaxy/web/controllers/requests.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/web/controllers/requests.py Wed Sep 09 14:24:11 2009 -0400
@@ -4,13 +4,12 @@
from galaxy.datatypes import sniff
from galaxy import util
from galaxy.util.streamball import StreamBall
+from galaxy.util.odict import odict
import logging, tempfile, zipfile, tarfile, os, sys
from galaxy.web.form_builder import *
from datetime import datetime, timedelta
from cgi import escape, FieldStorage
from galaxy.web.controllers.forms import get_form_widgets
-from galaxy.web.controllers.library import get_authorized_libs
-
log = logging.getLogger( __name__ )
@@ -432,8 +431,6 @@
return self.__show_request_form(trans, **kwd)
elif params.get('refresh', False) == 'true':
return self.__show_request_form(trans, **kwd)
-
-
def __show_request_form(self, trans, **kwd):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
@@ -460,7 +457,25 @@
helptext='(Optional)'))
# libraries selectbox
- libraries = get_authorized_libs(trans, trans.user)
+ all_libraries = trans.app.model.Library.filter( trans.app.model.Library.table.c.deleted == False ) \
+ .order_by( trans.app.model.Library.name ).all()
+ user, roles = trans.get_user_and_roles()
+ actions_to_check = [ trans.app.security_agent.permitted_actions.LIBRARY_ADD ]
+ # The libraries dictionary looks like: { library : '1,2' }, library : '3' }
+ # Its keys are the libraries that should be displayed for the current user and whose values are a
+ # string of comma-separated folder ids, of the associated folders the should NOT be displayed.
+ # The folders that should not be displayed may not be a complete list, but it is ultimately passed
+ # to the calling method to keep from re-checking the same folders when the library / folder
+ # select lists are rendered.
+ #
+ # TODO: RC, when you add the folders select list to your request form, take advantage of the hidden_folder_ids
+ # so that you do not need to check those same folders yet again when populating the select list.
+ #
+ libraries = odict()
+ for library in all_libraries:
+ can_show, hidden_folder_ids = trans.app.security_agent.show_library_item( user, roles, library, actions_to_check )
+ if can_show:
+ libraries[ library ] = hidden_folder_ids
libui = self.__library_ui(libraries, **kwd)
widgets = widgets + libui
widgets = widgets + get_form_widgets(trans, request_type.request_form, contents=[], **kwd)
@@ -470,12 +485,10 @@
widgets=widgets,
msg=msg,
messagetype=messagetype)
-
def __library_ui(self, libraries, request=None, **kwd):
params = util.Params( kwd )
lib_id = params.get( 'library_id', 'none' )
- lib_list = SelectField('library_id', refresh_on_change=True,
- refresh_on_change_values=['new'])
+ lib_list = SelectField( 'library_id', refresh_on_change=True, refresh_on_change_values=['new'] )
if request and lib_id == 'none':
if request.library:
lib_id = str(request.library.id)
@@ -483,7 +496,7 @@
lib_list.add_option('Select one', 'none', selected=True)
else:
lib_list.add_option('Select one', 'none')
- for lib in libraries:
+ for lib, hidden_folder_ids in libraries.items():
if str(lib.id) == lib_id:
lib_list.add_option(lib.name, lib.id, selected=True)
else:
@@ -653,9 +666,27 @@
widgets.append(dict(label='Description',
widget=TextField('desc', 40, desc),
helptext='(Optional)'))
-
# libraries selectbox
- libraries = get_authorized_libs(trans, trans.user)
+ all_libraries = trans.app.model.Library.filter( trans.app.model.Library.table.c.deleted == False ) \
+ .order_by( trans.app.model.Library.name ).all()
+ user, roles = trans.get_user_and_roles()
+ actions_to_check = [ trans.app.security_agent.permitted_actions.LIBRARY_ADD ]
+ # The libraries dictionary looks like:
+ # { library : '1,2' }, library : '3' }
+ # Its keys are the libraries that should be displayed for the current user and whose values are a
+ # string of comma-separated folder ids, of the associated folders the should NOT be displayed.
+ # The folders that should not be displayed may not be a complete list, but it is ultimately passed
+ # to the calling method to keep from re-checking the same folders when the library / folder
+ # select lists are rendered.
+ #
+ # TODO: RC, when you add the folders select list to your request form, take advantage of the hidden_folder_ids
+ # so that you do not need to check those same folders yet again when populating the select list.
+ #
+ libraries = {}
+ for library in all_libraries:
+ can_show, hidden_folder_ids = trans.app.security_agent.show_library_item( user, roles, library, actions_to_check )
+ if can_show:
+ libraries[ library ] = hidden_folder_ids
libui = self.__library_ui(libraries, request, **kwd)
widgets = widgets + libui
widgets = widgets + get_form_widgets(trans, request.type.request_form, request.values.content, **kwd)
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/web/controllers/requests_admin.py
--- a/lib/galaxy/web/controllers/requests_admin.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/web/controllers/requests_admin.py Wed Sep 09 14:24:11 2009 -0400
@@ -8,7 +8,6 @@
from galaxy.web.form_builder import *
from datetime import datetime, timedelta
from galaxy.web.controllers.forms import get_form_widgets
-from galaxy.web.controllers.library import get_authorized_libs
log = logging.getLogger( __name__ )
@@ -709,14 +708,32 @@
return select_user
def __library_ui(self, trans, user, request=None, **kwd):
+ """
+ Return a list of libraries for which user has the permission
+ to perform the LIBRARY_ADD action on any of it's folders
+ """
params = util.Params( kwd )
lib_id = params.get( 'library_id', 'none' )
- if not user:
- libraries = trans.app.model.Library.filter(trans.app.model.Library.table.c.deleted == False).order_by(trans.app.model.Library.name).all()
- else:
- libraries = get_authorized_libs(trans, user)
- lib_list = SelectField('library_id', refresh_on_change=True,
- refresh_on_change_values=['new'])
+ all_libraries = trans.app.model.Library.filter( trans.app.model.Library.table.c.deleted == False ) \
+ .order_by( trans.app.model.Library.name ).all()
+ roles = user.all_roles()
+ actions_to_check = [ trans.app.security_agent.permitted_actions.LIBRARY_ADD ]
+ # The libraries dictionary looks like: { library : '1,2' }, library : '3' }
+ # Its keys are the libraries that should be displayed for the current user and whose values are a
+ # string of comma-separated folder ids, of the associated folders the should NOT be displayed.
+ # The folders that should not be displayed may not be a complete list, but it is ultimately passed
+ # to the calling method to keep from re-checking the same folders when the library / folder
+ # select lists are rendered.
+ #
+ # TODO: RC, when you add the folders select list to your request form, take advantage of the hidden_folder_ids
+ # so that you do not need to check those same folders yet again when populating the select list.
+ #
+ libraries = {}
+ for library in all_libraries:
+ can_show, hidden_folder_ids = trans.app.security_agent.show_library_item( user, roles, library, actions_to_check )
+ if can_show:
+ libraries[ library ] = hidden_folder_ids
+ lib_list = SelectField( 'library_id', refresh_on_change=True, refresh_on_change_values=['new'] )
if request and lib_id == 'none':
if request.library:
lib_id = str(request.library.id)
@@ -724,7 +741,7 @@
lib_list.add_option('Select one', 'none', selected=True)
else:
lib_list.add_option('Select one', 'none')
- for lib in libraries:
+ for lib, hidden_folder_ids in libraries.items():
if str(lib.id) == lib_id:
lib_list.add_option(lib.name, lib.id, selected=True)
else:
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/web/controllers/root.py
--- a/lib/galaxy/web/controllers/root.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/web/controllers/root.py Wed Sep 09 14:24:11 2009 -0400
@@ -153,10 +153,7 @@
return "Dataset id '%s' is invalid" %str( id )
if data:
user, roles = trans.get_user_and_roles()
- if trans.app.security_agent.allow_action( user,
- roles,
- data.permitted_actions.DATASET_ACCESS,
- dataset = data.dataset ):
+ if trans.app.security_agent.can_access_dataset( roles, data.dataset ):
mime = trans.app.datatypes_registry.get_mimetype_by_extension( data.extension.lower() )
trans.response.set_content_type(mime)
if tofile:
@@ -189,10 +186,7 @@
child = data.get_child_by_designation( designation )
if child:
user, roles = trans.get_user_and_roles()
- if trans.app.security_agent.allow_action( user,
- roles,
- child.permitted_actions.DATASET_ACCESS,
- dataset = child ):
+ if trans.app.security_agent.can_access_dataset( roles, child ):
return self.display( trans, id=child.id, tofile=tofile, toext=toext )
else:
return "You are not privileged to access this dataset."
@@ -209,10 +203,7 @@
authz_method = kwd['authz_method']
if data:
user, roles = trans.get_user_and_roles()
- if authz_method == 'rbac' and trans.app.security_agent.allow_action( user,
- roles,
- data.permitted_actions.DATASET_ACCESS,
- dataset = data ):
+ if authz_method == 'rbac' and trans.app.security_agent.can_access_dataset( roles, data ):
trans.response.set_content_type( data.get_mime() )
trans.log_event( "Formatted dataset id %s for display at %s" % ( str( id ), display_app ) )
return data.as_display_type( display_app, **kwd )
@@ -262,10 +253,7 @@
if id is not None and data.history.user is not None and data.history.user != trans.user:
return trans.show_error_message( "This instance of a dataset (%s) in a history does not belong to you." % ( data.id ) )
user, roles = trans.get_user_and_roles()
- if trans.app.security_agent.allow_action( user,
- roles,
- data.permitted_actions.DATASET_ACCESS,
- dataset=data.dataset ):
+ if trans.app.security_agent.can_access_dataset( roles, data.dataset ):
if data.state == trans.model.Dataset.states.UPLOAD:
return trans.show_error_message( "Please wait until this dataset finishes uploading before attempting to edit its metadata." )
params = util.Params( kwd, safe=False )
@@ -331,10 +319,7 @@
elif params.update_roles_button:
if not trans.user:
return trans.show_error_message( "You must be logged in if you want to change permissions." )
- if trans.app.security_agent.allow_action( user,
- roles,
- data.dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS,
- dataset = data.dataset ):
+ if trans.app.security_agent.can_manage_dataset( roles, data.dataset ):
permissions = {}
for k, v in trans.app.model.Dataset.permitted_actions.items():
in_roles = params.get( k + '_in', [] )
diff -r eba44fc830bf -r c3b40f23a0e0 lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py Tue Sep 08 17:33:38 2009 -0400
+++ b/lib/galaxy/web/framework/__init__.py Wed Sep 09 14:24:11 2009 -0400
@@ -503,7 +503,7 @@
if user:
roles = user.all_roles()
else:
- roles = None
+ roles = []
return user, roles
def user_is_admin( self ):
diff -r eba44fc830bf -r c3b40f23a0e0 static/images/pileup_parser_help1.png
Binary file static/images/pileup_parser_help1.png has changed
diff -r eba44fc830bf -r c3b40f23a0e0 static/images/pileup_parser_help2.png
Binary file static/images/pileup_parser_help2.png has changed
diff -r eba44fc830bf -r c3b40f23a0e0 templates/admin/library/browse_library.mako
--- a/templates/admin/library/browse_library.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/admin/library/browse_library.mako Wed Sep 09 14:24:11 2009 -0400
@@ -1,17 +1,15 @@
<%inherit file="/base.mako"/>
-<%namespace file="common.mako" import="render_dataset" />
<%namespace file="/message.mako" import="render_msg" />
-<% from galaxy import util %>
+<%
+ from time import strftime
+ from galaxy import util
+ from galaxy.web.controllers.library import active_folders_and_lddas, activatable_folders_and_lddas
+%>
<%def name="stylesheets()">
<link href="${h.url_for('/static/style/base.css')}" rel="stylesheet" type="text/css" />
<link href="${h.url_for('/static/style/library.css')}" rel="stylesheet" type="text/css" />
</%def>
-
-<%
-def name_sorted( l ):
- return sorted( l, lambda a, b: cmp( a.name.lower(), b.name.lower() ) )
-%>
<script type="text/javascript">
$( document ).ready( function () {
@@ -72,24 +70,77 @@
}
</script>
-<%def name="render_folder( folder, folder_pad, deleted, show_deleted, created_ldda_ids, library_id )">
+<%def name="render_dataset( ldda, library_dataset, selected, library, folder, deleted, show_deleted )">
<%
- root_folder = not folder.parent
+ ## The received data must always be a LibraryDatasetDatasetAssociation object. The object id passed to methods
+ ## from the drop down menu should be the ldda id to prevent id collision ( which could happen when displaying
+ ## children, which are always lddas ). We also need to make sure we're displaying the latest version of this
+ ## library_dataset, so we display the attributes from the ldda.
+ if ldda.user:
+ uploaded_by = ldda.user.email
+ else:
+ uploaded_by = 'anonymous'
+ if ldda == library_dataset.library_dataset_dataset_association:
+ current_version = True
+ else:
+ current_version = False
+ %>
+ <div class="historyItemWrapper historyItem historyItem-${ldda.state}" id="libraryItem-${ldda.id}">
+ ## Header row for library items (name, state, action buttons)
+ <div class="historyItemTitleBar">
+ <table cellspacing="0" cellpadding="0" border="0" width="100%">
+ <tr>
+ <td width="*">
+ %if selected:
+ <input type="checkbox" name="ldda_ids" value="${ldda.id}" checked/>
+ %else:
+ <input type="checkbox" name="ldda_ids" value="${ldda.id}"/>
+ %endif
+ <span class="libraryItemDeleted-${ldda.deleted}">
+ <a href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library.id, folder_id=folder.id, id=ldda.id, info=True, deleted=deleted, show_deleted=show_deleted )}"><b>${ldda.name[:50]}</b></a>
+ </span>
+ <a id="dataset-${ldda.id}-popup" class="popup-arrow" style="display: none;">▼</a>
+ %if not library.deleted and not folder.deleted and not library_dataset.deleted:
+ <div popupmenu="dataset-${ldda.id}-popup">
+ <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library.id, folder_id=folder.id, id=ldda.id, edit_info=True )}">Edit this dataset's information</a>
+ ## We're disabling the ability to add templates at the LDDA and LibraryDataset level, but will leave this here for possible future use
+ ##<a class="action-button" href="${h.url_for( controller='admin', action='info_template', library_id=library.id, library_dataset_id=library_dataset.id, new_template=True )}">Add an information template to this dataset</a>
+ <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library.id, folder_id=folder.id, id=ldda.id, permissions=True )}">Edit this dataset's permissions</a>
+ %if current_version:
+ <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library.id, folder_id=folder.id, replace_id=library_dataset.id )}">Upload a new version of this dataset</a>
+ %endif
+ %if ldda.has_data:
+ <a class="action-button" href="${h.url_for( controller='admin', action='download_dataset_from_folder', id=ldda.id, library_id=library.id )}">Download this dataset</a>
+ %endif
+ <a class="action-button" confirm="Click OK to delete dataset '${ldda.name}'." href="${h.url_for( controller='admin', action='delete_library_item', library_id=library.id, library_item_id=library_dataset.id, library_item_type='library_dataset' )}">Delete this dataset</a>
+ </div>
+ %elif not library.deleted and not folder.deleted and library_dataset.deleted:
+ <div popupmenu="dataset-${ldda.id}-popup">
+ <a class="action-button" href="${h.url_for( controller='admin', action='undelete_library_item', library_id=library.id, library_item_id=library_dataset.id, library_item_type='library_dataset' )}">Undelete this dataset</a>
+ </div>
+ %endif
+ </td>
+ <td width="300">${ldda.message}</td>
+ <td width="150">${uploaded_by}</td>
+ <td width="60">${ldda.create_time.strftime( "%Y-%m-%d" )}</td>
+ </tr>
+ </table>
+ </div>
+ </div>
+</%def>
+
+<%def name="render_folder( folder, folder_pad, deleted, show_deleted, created_ldda_ids, library_id, root_folder=False )">
+ <%
if root_folder:
pad = folder_pad
+ expander = "/static/images/silk/resultset_bottom.png"
+ folder_img = "/static/images/silk/folder_page.png"
else:
pad = folder_pad + 20
- if folder_pad == 0:
- expander = "/static/images/silk/resultset_bottom.png"
- folder_img = "/static/images/silk/folder_page.png"
- subfolder = False
- else:
expander = "/static/images/silk/resultset_next.png"
folder_img = "/static/images/silk/folder.png"
- subfolder = True
- created_ldda_id_list = util.listify( created_ldda_ids )
- if created_ldda_id_list:
- created_ldda_ids = [ int( ldda_id ) for ldda_id in created_ldda_id_list ]
+ if created_ldda_ids:
+ created_ldda_ids = [ int( ldda_id ) for ldda_id in util.listify( created_ldda_ids ) ]
%>
%if not root_folder:
<li class="folderRow libraryOrFolderRow" style="padding-left: ${pad}px;">
@@ -104,10 +155,6 @@
</div>
%endif
%if not folder.deleted:
- <%
- library_item_ids = {}
- library_item_ids[ 'folder' ] = folder.id
- %>
<div popupmenu="folder-${folder.id}-popup">
<a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library_id, folder_id=folder.id )}">Add datasets to this folder</a>
<a class="action-button" href="${h.url_for( controller='admin', action='folder', new=True, id=folder.id, library_id=library_id )}">Create a new sub-folder in this folder</a>
@@ -130,30 +177,31 @@
%endif
</li>
%endif
- %if subfolder:
+ %if pad > 0:
<ul id="subFolder">
%else:
<ul>
%endif
%if show_deleted:
<%
- parent_folders = folder.activatable_folders
- parent_datasets = folder.activatable_library_datasets
+ sub_folders, lddas = activatable_folders_and_lddas( trans, folder )
%>
%else:
<%
- parent_folders = folder.active_folders
- parent_datasets = folder.active_library_datasets
+ sub_folders, lddas = active_folders_and_lddas( trans, folder )
%>
%endif
- %for folder in name_sorted( parent_folders ):
- ${render_folder( folder, pad, deleted, show_deleted, created_ldda_ids, library_id )}
- %endfor
- %for library_dataset in name_sorted( parent_datasets ):
+ %for sub_folder in sub_folders:
+ ${render_folder( sub_folder, pad, deleted, show_deleted, created_ldda_ids, library_id )}
+ %endfor
+ %for ldda in lddas:
<%
- selected = created_ldda_ids and library_dataset.library_dataset_dataset_association.id in created_ldda_ids
+ library_dataset = ldda.library_dataset
+ selected = created_ldda_ids and ldda.id in created_ldda_ids
%>
- <li class="datasetRow" style="padding-left: ${pad + 18}px;">${render_dataset( library_dataset, selected, library, deleted, show_deleted )}</li>
+ <li class="datasetRow" style="padding-left: ${pad + 18}px;">
+ ${render_dataset( ldda, library_dataset, selected, library, folder, deleted, show_deleted )}
+ </li>
%endfor
</ul>
</%def>
@@ -196,10 +244,6 @@
<a id="library-${library.id}-popup" class="popup-arrow" style="display: none;">▼</a>
<div popupmenu="library-${library.id}-popup">
%if not deleted:
- <%
- library_item_ids = {}
- library_item_ids[ 'library' ] = library.id
- %>
<a class="action-button" href="${h.url_for( controller='admin', action='library', id=library.id, information=True )}">Edit this data library's information</a>
## Editing templates disabled until we determine optimal approach to re-linking library item to new version of form definition
##%if library.info_association:
@@ -228,7 +272,7 @@
</div>
</li>
<ul>
- ${render_folder( library.root_folder, 0, deleted, show_deleted, created_ldda_ids, library.id )}
+ ${render_folder( library.root_folder, 0, deleted, show_deleted, created_ldda_ids, library.id, root_folder=True )}
</ul>
<br/>
</ul>
diff -r eba44fc830bf -r c3b40f23a0e0 templates/admin/library/common.mako
--- a/templates/admin/library/common.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/admin/library/common.mako Wed Sep 09 14:24:11 2009 -0400
@@ -1,68 +1,3 @@
-<% from time import strftime %>
-
-<%def name="render_dataset( library_dataset, selected, library, deleted, show_deleted )">
- <%
- ## The received data must always be a LibraryDataset object, but the object id passed to methods from the drop down menu
- ## should be the underlying ldda id to prevent id collision ( which could happen when displaying children, which are always
- ## lddas ). We also need to make sure we're displaying the latest version of this library_dataset, so we display the attributes
- ## from the ldda.
- ldda = library_dataset.library_dataset_dataset_association
- if ldda.user:
- uploaded_by = ldda.user.email
- else:
- uploaded_by = 'anonymous'
- if ldda == ldda.library_dataset.library_dataset_dataset_association:
- current_version = True
- else:
- current_version = False
- %>
- <div class="historyItemWrapper historyItem historyItem-${ldda.state}" id="libraryItem-${ldda.id}">
- ## Header row for library items (name, state, action buttons)
- <div class="historyItemTitleBar">
- <table cellspacing="0" cellpadding="0" border="0" width="100%">
- <tr>
- <td width="*">
- %if selected:
- <input type="checkbox" name="ldda_ids" value="${ldda.id}" checked/>
- %else:
- <input type="checkbox" name="ldda_ids" value="${ldda.id}"/>
- %endif
- <span class="libraryItemDeleted-${library_dataset.deleted}">
- <a href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, info=True, deleted=deleted, show_deleted=show_deleted )}"><b>${ldda.name[:50]}</b></a>
- </span>
- <a id="dataset-${ldda.id}-popup" class="popup-arrow" style="display: none;">▼</a>
- %if not library.deleted and not library_dataset.folder.deleted and not library_dataset.deleted:
- <%
- library_item_ids = {}
- library_item_ids[ 'ldda' ] = ldda.id
- %>
- <div popupmenu="dataset-${ldda.id}-popup">
- <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, edit_info=True )}">Edit this dataset's information</a>
- ## We're disabling the ability to add templates at the LDDA and LibraryDataset level, but will leave this here for possible future use
- ##<a class="action-button" href="${h.url_for( controller='admin', action='info_template', library_id=library.id, library_dataset_id=library_dataset.id, new_template=True )}">Add an information template to this dataset</a>
- <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, permissions=True )}">Edit this dataset's permissions</a>
- %if current_version:
- <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, replace_id=library_dataset.id )}">Upload a new version of this dataset</a>
- %endif
- %if ldda.has_data:
- <a class="action-button" href="${h.url_for( controller='admin', action='download_dataset_from_folder', id=ldda.id, library_id=library.id )}">Download this dataset</a>
- %endif
- <a class="action-button" confirm="Click OK to delete dataset '${ldda.name}'." href="${h.url_for( controller='admin', action='delete_library_item', library_id=library.id, library_item_id=library_dataset.id, library_item_type='library_dataset' )}">Delete this dataset</a>
- </div>
- %elif not library.deleted and not library_dataset.folder.deleted and library_dataset.deleted:
- <div popupmenu="dataset-${ldda.id}-popup">
- <a class="action-button" href="${h.url_for( controller='admin', action='undelete_library_item', library_id=library.id, library_item_id=library_dataset.id, library_item_type='library_dataset' )}">Undelete this dataset</a>
- </div>
- %endif
- </td>
- <td width="300">${ldda.message}</td>
- <td width="150">${uploaded_by}</td>
- <td width="60">${ldda.create_time.strftime( "%Y-%m-%d" )}</td>
- </tr>
- </table>
- </div>
- </div>
-</%def>
<%def name="render_template_info( library_item, library_id, widgets, editable=True )">
<%
diff -r eba44fc830bf -r c3b40f23a0e0 templates/admin/library/ldda_info.mako
--- a/templates/admin/library/ldda_info.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/admin/library/ldda_info.mako Wed Sep 09 14:24:11 2009 -0400
@@ -86,26 +86,14 @@
<div class="form-row">
<div>${ldda.blurb}</div>
</div>
- <div class="form-row">
- <div id="info${ldda.id}" class="historyItemBody">
- %if ldda.peek != "no peek":
+ %if ldda.peek != "no peek":
+ <div class="form-row">
+ <div id="info${ldda.id}" class="historyItemBody">
<label>Peek:</label>
<div><pre id="peek${ldda.id}" class="peek">${ldda.display_peek()}</pre></div>
- %endif
- ## Recurse for child datasets
- %if len( ldda.visible_children ) > 0:
- <div>
- There are ${len( ldda.visible_children )} secondary datasets.
- %for idx, child in enumerate( ldda.visible_children ):
- ## TODO: do we need to clarify if the child is deleted?
- %if not child.purged:
- ${ render_dataset( child, selected, library, False, False ) }
- %endif
- %endfor
- </div>
- %endif
+ </div>
</div>
- </div>
+ %endif
</div>
%if widgets:
${render_template_info( ldda, library.id, widgets, editable=False )}
diff -r eba44fc830bf -r c3b40f23a0e0 templates/dataset/edit_attributes.mako
--- a/templates/dataset/edit_attributes.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/dataset/edit_attributes.mako Wed Sep 09 14:24:11 2009 -0400
@@ -189,7 +189,7 @@
</div>
<p />
-%if trans.app.security_agent.allow_action( user, user_roles, data.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset=data.dataset ):
+%if trans.app.security_agent.can_manage_dataset( user_roles, data.dataset ):
<%namespace file="/dataset/security_common.mako" import="render_permission_form" />
${render_permission_form( data.dataset, data.name, h.url_for( controller='root', action='edit', id=data.id ), user_roles )}
%elif trans.user:
diff -r eba44fc830bf -r c3b40f23a0e0 templates/library/browse_libraries.mako
--- a/templates/library/browse_libraries.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/library/browse_libraries.mako Wed Sep 09 14:24:11 2009 -0400
@@ -20,9 +20,9 @@
</tr>
</thead>
<tbody>
- %for library in libraries:
+ %for library, hidden_folder_ids in libraries.items():
<tr class="libraryRow libraryOrFolderRow" id="libraryRow">
- <td><a href="${h.url_for( controller='library', action='browse_library', id=library.id )}">${library.name}</a></td>
+ <td><a href="${h.url_for( controller='library', action='browse_library', id=library.id, hidden_folder_ids=hidden_folder_ids )}">${library.name}</a></td>
<td><i>${library.description}</i></td>
</tr>
%endfor
diff -r eba44fc830bf -r c3b40f23a0e0 templates/library/browse_library.mako
--- a/templates/library/browse_library.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/library/browse_library.mako Wed Sep 09 14:24:11 2009 -0400
@@ -2,8 +2,8 @@
<%namespace file="/message.mako" import="render_msg" />
<%
from galaxy import util
+ from galaxy.web.controllers.library import active_folders
from time import strftime
-
user, roles = trans.get_user_and_roles()
%>
@@ -14,10 +14,6 @@
</%def>
<%
-
-def name_sorted( l ):
- return sorted( l, lambda a, b: cmp( a.name.lower(), b.name.lower() ) )
-
class RowCounter( object ):
def __init__( self ):
self.count = 0
@@ -83,21 +79,22 @@
});
</script>
-<%def name="render_dataset( library_dataset, selected, library, pad, parent, row_conter )">
+<%def name="render_dataset( ldda, library_dataset, selected, library, folder, pad, parent, row_conter )">
<%
- ## The received data must always be a LibraryDataset object, but the object id passed to methods from the drop down menu
- ## should be the underlying ldda id to prevent id collision ( which could happen when displaying children, which are always
- ## lddas ). We also need to make sure we're displaying the latest version of this library_dataset, so we display the attributes
+ ## The id passed to methods from the drop down menu should be the ldda id to prevent id collision
+ ## ( which could happen when displaying children, which are always lddas ). We also need to make
+ ## sure we're displaying the latest version of this library_dataset, so we display the attributes
## from the ldda.
- ldda = library_dataset.library_dataset_dataset_association
if ldda.user:
uploaded_by = ldda.user.email
else:
uploaded_by = 'anonymous'
- if ldda == ldda.library_dataset.library_dataset_dataset_association:
+ if ldda == library_dataset.library_dataset_dataset_association:
current_version = True
else:
current_version = False
+ can_modify_library_dataset = trans.app.security_agent.can_modify_library_item( user, roles, library_dataset )
+ can_manage_library_dataset = trans.app.security_agent.can_manage_library_item( user, roles, library_dataset )
%>
<tr class="datasetRow"
@@ -112,19 +109,19 @@
%else:
<input type="checkbox" name="ldda_ids" value="${ldda.id}"/>
%endif
- <a href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, info=True )}"><b>${ldda.name[:60]}</b></a>
+ <a href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=folder.id, id=ldda.id, info=True )}"><b>${ldda.name[:60]}</b></a>
<a id="dataset-${ldda.id}-popup" class="popup-arrow" style="display: none;">▼</a>
<div popupmenu="dataset-${ldda.id}-popup">
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
- <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, edit_info=True )}">Edit this dataset's information</a>
+ %if can_modify_library_dataset:
+ <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=folder.id, id=ldda.id, edit_info=True )}">Edit this dataset's information</a>
%else:
- <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, information=True )}">View this dataset's information</a>
+ <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=folder.id, id=ldda.id, information=True )}">View this dataset's information</a>
%endif
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset=ldda.dataset ) and trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=ldda.library_dataset ):
- <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, permissions=True )}">Edit this dataset's permissions</a>
- %if current_version and trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
- <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, replace_id=library_dataset.id )}">Upload a new version of this dataset</a>
+ %if can_manage_library_dataset:
+ <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=folder.id, id=ldda.id, permissions=True )}">Edit this dataset's permissions</a>
%endif
+ %if current_version and can_modify_library_dataset:
+ <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=folder.id, replace_id=library_dataset.id )}">Upload a new version of this dataset</a>
%endif
%if ldda.has_data:
<a class="action-button" href="${h.url_for( controller='library', action='datasets', library_id=library.id, ldda_ids=str( ldda.id ), do_action='add' )}">Import this dataset into your current history</a>
@@ -142,31 +139,30 @@
%>
</%def>
-<%def name="render_folder( folder, folder_pad, created_ldda_ids, library_id, parent=None, row_counter=None )">
+<%def name="render_folder( folder, folder_pad, created_ldda_ids, library_id, hidden_folder_ids, parent=None, row_counter=None, root_folder=False )">
<%
- def show_folder():
- ## TODO: instead of calling check_folder_contents(), which we've already done prior to getting here,
- ## add a new method that will itself call check_folder_contents() and build a list of accessible folders
- ## for each library - this should improve performance dor large libraries where the current user can only
- ## access a small number of folders.
- if trans.app.security_agent.check_folder_contents( user, roles, folder ) or \
- trans.app.security_agent.show_library_item( user, roles, folder ):
- return True
- return False
- if not show_folder:
+ if str( folder.id ) in hidden_folder_ids:
return ""
- root_folder = not folder.parent
+ can_access, folder_ids = trans.app.security_agent.check_folder_contents( user, roles, folder )
+ if not can_access:
+ can_show, folder_ids = \
+ trans.app.security_agent.show_library_item( user,
+ roles,
+ folder,
+ [ trans.app.security_agent.permitted_actions.LIBRARY_ADD,
+ trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
+ trans.app.security_agent.permitted_actions.LIBRARY_MANAGE ] )
+ if not can_show:
+ return ""
if root_folder:
pad = folder_pad
else:
pad = folder_pad + 20
- if folder_pad == 0:
- subfolder = False
- else:
- subfolder = True
- created_ldda_id_list = util.listify( created_ldda_ids )
- if created_ldda_id_list:
- created_ldda_ids = [ int( ldda_id ) for ldda_id in created_ldda_id_list ]
+ if created_ldda_ids:
+ created_ldda_ids = [ int( ldda_id ) for ldda_id in util.listify( created_ldda_ids ) ]
+ can_add = trans.app.security_agent.can_add_library_item( user, roles, folder )
+ can_modify = trans.app.security_agent.can_modify_library_item( user, roles, folder )
+ can_manage = trans.app.security_agent.can_manage_library_item( user, roles, folder )
my_row = None
%>
%if not root_folder:
@@ -186,21 +182,19 @@
%endif
<a id="folder_img-${folder.id}-popup" class="popup-arrow" style="display: none;">▼</a>
<div popupmenu="folder_img-${folder.id}-popup">
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=folder ):
+ %if can_add:
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library_id, folder_id=folder.id )}">Add datasets to this folder</a>
<a class="action-button" href="${h.url_for( controller='library', action='folder', new=True, id=folder.id, library_id=library_id )}">Create a new sub-folder in this folder</a>
%endif
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=folder ):
+ %if can_modify:
<a class="action-button" href="${h.url_for( controller='library', action='folder', information=True, id=folder.id, library_id=library_id )}">Edit this folder's information</a>
%else:
<a class="action-button" href="${h.url_for( controller='library', action='folder', information=True, id=folder.id, library_id=library_id )}">View this folder's information</a>
%endif
- %if forms and not folder.info_association:
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library ):
- <a class="action-button" href="${h.url_for( controller='library', action='info_template', library_id=library.id, add=True )}">Add an information template to this folder</a>
- %endif
+ %if can_add and forms and not folder.info_association:
+ <a class="action-button" href="${h.url_for( controller='library', action='info_template', library_id=library.id, add=True )}">Add an information template to this folder</a>
%endif
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=folder ):
+ %if can_manage:
<a class="action-button" href="${h.url_for( controller='library', action='folder', permissions=True, id=folder.id, library_id=library_id )}">Edit this folder's permissions</a>
%endif
</div>
@@ -212,43 +206,48 @@
row_counter.increment()
%>
%endif
- %for child_folder in name_sorted( folder.active_folders ):
- ${render_folder( child_folder, pad, created_ldda_ids, library_id, my_row, row_counter )}
+ <% sub_folders = active_folders( trans, folder ) %>
+ %for sub_folder in sub_folders:
+ ${render_folder( sub_folder, pad, created_ldda_ids, library_id, hidden_folder_ids, parent=my_row, row_counter=row_counter )}
%endfor
- %for library_dataset in name_sorted( folder.active_library_datasets ):
+ %for library_dataset in folder.active_library_datasets:
<%
- selected = created_ldda_ids and library_dataset.library_dataset_dataset_association.id in created_ldda_ids
+ ldda = library_dataset.library_dataset_dataset_association
+ can_access = trans.app.security_agent.can_access_dataset( roles, ldda.dataset )
+ selected = created_ldda_ids and ldda.id in created_ldda_ids
%>
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.DATASET_ACCESS, dataset=library_dataset.library_dataset_dataset_association.dataset ):
- ${render_dataset( library_dataset, selected, library, pad, my_row, row_counter )}
+ %if can_access:
+ ${render_dataset( ldda, library_dataset, selected, library, folder, pad, my_row, row_counter )}
%endif
%endfor
</%def>
<h2>Data Library “${library.name}”</h2>
+<%
+can_add = trans.app.security_agent.can_add_library_item( user, roles, library )
+can_modify = trans.app.security_agent.can_modify_library_item( user, roles, library )
+can_manage = trans.app.security_agent.can_manage_library_item( user, roles, library )
+%>
+
<ul class="manage-table-actions">
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library ):
- %if not deleted:
- <li>
- <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library.root_folder.id )}"><span>Add datasets to this library</span></a>
- </li>
- <li>
- <a class="action-button" href="${h.url_for( controller='library', action='folder', new=True, id=library.root_folder.id, library_id=library.id )}">Add a folder to this library</a>
- </li>
- %endif
+ %if can_add and not_deleted:
+ <li>
+ <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library.root_folder.id )}"><span>Add datasets to this library</span></a>
+ </li>
+ <li>
+ <a class="action-button" href="${h.url_for( controller='library', action='folder', new=True, id=library.root_folder.id, library_id=library.id )}">Add a folder to this library</a>
+ </li>
%endif
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library ):
+ %if can_modify:
<li><a class="action-button" href="${h.url_for( controller='library', action='library', information=True, id=library.id )}">Edit this library's information</a></li>
%else:
<li><a class="action-button" href="${h.url_for( controller='library', action='library', information=True, id=library.id )}">View this library's information</a></li>
%endif
- %if forms and not library.info_association:
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library ):
- <a class="action-button" href="${h.url_for( controller='library', action='info_template', library_id=library.id, add=True )}">Add an information template to this library</a>
- %endif
+ %if can_add and forms and not library.info_association:
+ <a class="action-button" href="${h.url_for( controller='library', action='info_template', library_id=library.id, add=True )}">Add an information template to this library</a>
%endif
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=library ):
+ %if can_manage:
<li><a class="action-button" href="${h.url_for( controller='library', action='library', permissions=True, id=library.id )}">Edit this library's permissions</a></li>
%endif
</ul>
@@ -258,10 +257,6 @@
%endif
<form name="import_from_library" action="${h.url_for( controller='library', action='datasets', library_id=library.id )}" method="post">
- <%
- library_item_ids = {}
- library_item_ids[ 'library' ] = library.id
- %>
<table cellspacing="0" cellpadding="0" border="0" width="100%" class="grid" id="library-grid">
<thead>
<tr class="libraryTitle">
@@ -272,7 +267,7 @@
</thead>
</tr>
<% row_counter = RowCounter() %>
- ${render_folder( library.root_folder, 0, created_ldda_ids, library.id, None, row_counter )}
+ ${render_folder( library.root_folder, 0, created_ldda_ids, library.id, hidden_folder_ids, parent=None, row_counter=row_counter, root_folder=True )}
<tfoot>
<tr>
<td colspan="4" style="padding-left: 42px;">
diff -r eba44fc830bf -r c3b40f23a0e0 templates/library/common.mako
--- a/templates/library/common.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/library/common.mako Wed Sep 09 14:24:11 2009 -0400
@@ -21,7 +21,7 @@
<div class="toolForm">
<div class="toolFormTitle">Other information about ${library_item_desc} ${library_item.name}</div>
<div class="toolFormBody">
- %if editable and trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library_item ):
+ %if editable and trans.app.security_agent.can_modify_library_item( user, roles, library_item ):
<form name="edit_info" action="${h.url_for( controller='library', action='edit_template_info', library_id=library_id, num_widgets=len( widgets ) )}" method="post">
<input type="hidden" name="library_item_id" value="${library_item.id}"/>
<input type="hidden" name="library_item_type" value="${library_item_type}"/>
diff -r eba44fc830bf -r c3b40f23a0e0 templates/library/folder_info.mako
--- a/templates/library/folder_info.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/library/folder_info.mako Wed Sep 09 14:24:11 2009 -0400
@@ -18,7 +18,7 @@
<div class="toolForm">
<div class="toolFormTitle">Edit folder name and description</div>
<div class="toolFormBody">
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=folder ):
+ %if trans.app.security_agent.can_modify_library_item( user, roles, folder ):
<form name="folder" action="${h.url_for( controller='library', action='folder', rename=True, id=folder.id, library_id=library_id )}" method="post" >
<div class="form-row">
<label>Name:</label>
diff -r eba44fc830bf -r c3b40f23a0e0 templates/library/folder_permissions.mako
--- a/templates/library/folder_permissions.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/library/folder_permissions.mako Wed Sep 09 14:24:11 2009 -0400
@@ -15,6 +15,6 @@
${render_msg( msg, messagetype )}
%endif
-%if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=folder ):
+%if trans.app.security_agent.can_manage_library_item( user, roles, folder ):
${render_permission_form( folder, folder.name, h.url_for( controller='library', action='folder', id=folder.id, library_id=library_id, permissions=True ), trans.user.all_roles() )}
%endif
diff -r eba44fc830bf -r c3b40f23a0e0 templates/library/ldda_edit_info.mako
--- a/templates/library/ldda_edit_info.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/library/ldda_edit_info.mako Wed Sep 09 14:24:11 2009 -0400
@@ -34,7 +34,7 @@
</select>
</%def>
-%if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
+%if trans.app.security_agent.can_modify_library_item( user, roles, ldda.library_dataset ):
<div class="toolForm">
<div class="toolFormTitle">Edit attributes of ${ldda.name}</div>
<div class="toolFormBody">
diff -r eba44fc830bf -r c3b40f23a0e0 templates/library/ldda_info.mako
--- a/templates/library/ldda_info.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/library/ldda_info.mako Wed Sep 09 14:24:11 2009 -0400
@@ -40,15 +40,15 @@
Information about ${ldda.name}
<a id="dataset-${ldda.id}-popup" class="popup-arrow" style="display: none;">▼</a>
<div popupmenu="dataset-${ldda.id}-popup">
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
+ %if trans.app.security_agent.can_modify_library_item( user, roles, ldda.library_dataset ):
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, id=ldda.id, edit_info=True )}">Edit this dataset's information</a>
%else:
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, id=ldda.id, information=True )}">View this dataset's information</a>
%endif
- %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset=ldda.dataset ) and trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=ldda.library_dataset ):
+ %if trans.app.security_agent.can_manage_dataset( roles, ldda.dataset ) and trans.app.security_agent.can_manage_library_item( user, roles, ldda.library_dataset ):
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, id=ldda.id, permissions=True )}">Edit this dataset's permissions</a>
%endif
- %if current_version and trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
+ %if current_version and trans.app.security_agent.can_modify_library_item( user, roles, ldda.library_dataset ):
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, replace_id=ldda.library_dataset.id )}">Upload a new version of this dataset</a>
%endif
%if ldda.has_data:
@@ -86,28 +86,14 @@
<div class="form-row">
<div>${ldda.blurb}</div>
</div>
- <div class="form-row">
- <div id="info${ldda.id}" class="historyItemBody">
- %if ldda.peek != "no peek":
+ %if ldda.peek != "no peek":
+ <div class="form-row">
+ <div id="info${ldda.id}" class="historyItemBody">
<label>Peek:</label>
<div><pre id="peek${ldda.id}" class="peek">${ldda.display_peek()}</pre></div>
- %endif
- ## Recurse for child datasets
- ## TODO: eliminate this - child datasets are deprecated, and where does
- ## render_dataset() come from anyway - it's not imported!
- %if len( ldda.visible_children ) > 0:
- <div>
- There are ${len( ldda.visible_children )} secondary datasets.
- %for idx, child in enumerate( ldda.visible_children ):
- ## TODO: do we need to clarify if the child is deleted?
- %if not child.purged:
- ${ render_dataset( child, selected, library ) }
- %endif
- %endfor
- </div>
- %endif
+ </div>
</div>
- </div>
+ %endif
</div>
%if widgets:
${render_template_info( ldda, library_id, widgets, editable=False )}
diff -r eba44fc830bf -r c3b40f23a0e0 templates/library/library_dataset_info.mako
--- a/templates/library/library_dataset_info.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/library/library_dataset_info.mako Wed Sep 09 14:24:11 2009 -0400
@@ -21,7 +21,7 @@
${render_msg( msg, messagetype )}
%endif
-%if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library_dataset ):
+%if trans.app.security_agent.can_modify_library_item( user, roles, library_dataset ):
<div class="toolForm">
<div class="toolFormTitle">Edit attributes of ${library_dataset.name}</div>
<div class="toolFormBody">
diff -r eba44fc830bf -r c3b40f23a0e0 templates/library/library_dataset_permissions.mako
--- a/templates/library/library_dataset_permissions.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/library/library_dataset_permissions.mako Wed Sep 09 14:24:11 2009 -0400
@@ -21,7 +21,7 @@
${render_msg( msg, messagetype )}
%endif
-%if trans.app.security_agent.allow_action( user, user_roles, trans.app.security_agent.permitted_actions.LIBRARY_manage, library_item=library_dataset ):
+%if trans.app.security_agent.can_manage_library_item( user, user_roles, library_dataset ):
<%
roles = trans.app.model.Role.filter( trans.app.model.Role.table.c.deleted==False ).order_by( trans.app.model.Role.table.c.name ).all()
%>
diff -r eba44fc830bf -r c3b40f23a0e0 templates/library/library_info.mako
--- a/templates/library/library_info.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/library/library_info.mako Wed Sep 09 14:24:11 2009 -0400
@@ -15,7 +15,7 @@
${render_msg( msg, messagetype )}
%endif
-%if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library ):
+%if trans.app.security_agent.can_modify_library_item( user, roles, library ):
<div class="toolForm">
<div class="toolFormTitle">Change library name and description</div>
<div class="toolFormBody">
diff -r eba44fc830bf -r c3b40f23a0e0 templates/library/library_permissions.mako
--- a/templates/library/library_permissions.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/library/library_permissions.mako Wed Sep 09 14:24:11 2009 -0400
@@ -15,7 +15,7 @@
${render_msg( msg, messagetype )}
%endif
-%if trans.app.security_agent.allow_action( user, user_roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=library ):
+%if trans.app.security_agent.can_manage_library_item( user, user_roles, library ):
<%
roles = trans.app.model.Role.filter( trans.app.model.Role.table.c.deleted==False ).order_by( trans.app.model.Role.table.c.name ).all()
%>
diff -r eba44fc830bf -r c3b40f23a0e0 templates/mobile/history/detail.mako
--- a/templates/mobile/history/detail.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/mobile/history/detail.mako Wed Sep 09 14:24:11 2009 -0400
@@ -37,7 +37,7 @@
<div class="secondary">
## Body for history items, extra info and actions, data "peek"
<% user, roles = trans.get_user_and_roles() %>
- %if not trans.app.security_agent.allow_action( user, roles, data.permitted_actions.DATASET_ACCESS, dataset = data.dataset ):
+ %if not trans.app.security_agent.can_access_dataset( roles, data.dataset ):
<div>You do not have permission to view this dataset.</div>
%elif data_state == "queued":
<div>Job is waiting to run</div>
diff -r eba44fc830bf -r c3b40f23a0e0 templates/mobile/manage_library.mako
--- a/templates/mobile/manage_library.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/mobile/manage_library.mako Wed Sep 09 14:24:11 2009 -0400
@@ -9,7 +9,7 @@
${render_msg( msg, messagetype )}
%endif
-%if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library ):
+%if trans.app.security_agent.can_modify_library_item( user, roles, library ):
<div class="toolForm">
<div class="toolFormTitle">Change library name and description</div>
<div class="toolFormBody">
@@ -55,7 +55,7 @@
</div>
</div>
%endif
-%if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=library ):
+%if trans.app.security_agent.can_manage_library_item( user, roles, library ):
<%
roles = trans.app.model.Role.filter( trans.app.model.Role.table.c.deleted==False ).order_by( trans.app.model.Role.table.c.name ).all()
%>
diff -r eba44fc830bf -r c3b40f23a0e0 templates/root/history_common.mako
--- a/templates/root/history_common.mako Tue Sep 08 17:33:38 2009 -0400
+++ b/templates/root/history_common.mako Wed Sep 09 14:24:11 2009 -0400
@@ -8,7 +8,7 @@
data_state = data.state
user, roles = trans.get_user_and_roles()
%>
- %if not trans.app.security_agent.allow_action( user, roles, data.permitted_actions.DATASET_ACCESS, dataset = data.dataset ):
+ %if not trans.app.security_agent.can_access_dataset( roles, data.dataset ):
<div class="historyItemWrapper historyItem historyItem-${data_state} historyItem-noPermission" id="historyItem-${data.id}">
%else:
<div class="historyItemWrapper historyItem historyItem-${data_state}" id="historyItem-${data.id}">
@@ -42,7 +42,7 @@
## Body for history items, extra info and actions, data "peek"
<div id="info${data.id}" class="historyItemBody">
- %if not trans.app.security_agent.allow_action( user, roles, data.permitted_actions.DATASET_ACCESS, dataset = data.dataset ):
+ %if not trans.app.security_agent.can_access_dataset( roles, data.dataset ):
<div>You do not have permission to view this dataset.</div>
%elif data_state == "upload":
<div>Dataset is uploading</div>
diff -r eba44fc830bf -r c3b40f23a0e0 test-data/cf_maf2fasta_new.dat
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cf_maf2fasta_new.dat Wed Sep 09 14:24:11 2009 -0400
@@ -0,0 +1,134 @@
+>hg17.chr7(+):127471195-127471526|sequence_index=0|block_index=0|species=hg17|hg17_0_0
+gtttgccatcttttgctgctctagggaatccagcagctgtcaccatgtaaacaagcccaggctagaccaGTTACCCTCATC---ATCTTAGCTGATAGCCAGCCAGCCACCACAGGCAtgagtcaggccatattgctggacccacagaattatgagctaaataaatagtcttgggttaagccactaagttttaggcatagtgtgttatgtaTCTCACAAACATATAAGACTGTGTGTTTGTTGACTGGAGGAAGAGATGCTATAAAGACCACCTTTTAAAACTTCCCAAATACTGCCACTGATGTCCTGATGGAGG-------------------------------------------------------TATGAA---------AACATCCACTAA
+>panTro1.chr6(+):129885076-129885407|sequence_index=0|block_index=0|species=panTro1|panTro1_0_0
+gtttgccatcttttgctgctcttgggaatccagcagctgtcaccatgtaaacaagcccaggctagaccaGTTACCCTCATC---ATCTTAGCTGATAGCCAGCCAGCCACCACAGGCAtgagtcaggccatattgctggacccacagaattatgagctaaataaatagtcttgggttaagccactaagttttaggcatagtgtgttatgtaTCTCACAAACATATAAGACTGTGTGTTTGTTGACTGGAGGAAGAGATGCTATAAAGACCACCTTTTGAAACTTCCCAAATACTGCCACTGATGTCCTGATGGAGG-------------------------------------------------------TATGAA---------AACATCCACTAA
+>rheMac2.chr3(+):165787989-165788319|sequence_index=0|block_index=0|species=rheMac2|rheMac2_0_0
+gcttgccatcttttgatgctcttgggaatccagcagctgtcaccat-taaacaagcccaggctagaccaGTTACCCTCATC---ATCTTAGCTGATAGCCAGCCAGCCACCATAGGCAtgagtcaggccatagtgctggacccacagaattatgagctaaataagtagtgttgggttaagtcactaagttttaggcatagtgtgttatgtagcTCACAAACATATAAGACTGTGTGTTTTTTGACTGGAGGAAGAGATGCCATAAAGACCACCTTTTGAAACTTCTCAAATACTGCCATTGATGTGCTGATGGAGG-------------------------------------------------------TATGAA---------AACATCCACTAA
+>rn3.chr4(+):56178191-56178473|sequence_index=0|block_index=0|species=rn3|rn3_0_0
+CTTCACTCTCATTTGCTGTT----------------CTGTCACTATGGAGACAAACACAGGCTAGCCCAGTTACTATCTTGATCACAGCAGCTGT----CAGCTAGCTGCCACTCACAGGAATAAGGCCATACCATT-GATCCACTGAACCTTGATCTAGGAATTTGGC----------------------TGGGGCCAGTTTGCGGTGTCACTCATGA--CTCTAAGATTGTGTGTTTG----CTCCAGGAAGAGACGGCAAGAGGATTACCTTTAAAAGGTTCGG-AGTCTAGCTGTAGACAGCCCAATGGG---------------------------------------------------------TATAAC---------AATACTCACTAA
+>mm7.chr6(+):28984529-28984886|sequence_index=0|block_index=0|species=mm7|mm7_0_0
+CTCCACTCTCGTTTGCTGTT----------------CTGTCACCATGGAAACAAACG-AGGGTGGTCCAGTTACTATCTTG---ACTGCAGCTGG----CAGTCAGTTGCCACT--CAGGAATAAGGCTATGCCATT-GATCCACTGAACCGTGATCTGGAAACCTGGCTGTTGTTT-------CAAGCCTTGGGGCCAGTTTGCGGTGTTACTCATGA--CTCTAAGATCGTGTGCTTG----CTGCAGGAAGAGACAGCAAGGGGGTTACATTTAAAAAGCCCCC-AGTTTAGCTATAGGCAGGCCAACAGGTGTAAAAATACTCACTAGTAATGGGCTGAACTCATGGAGGTAGCATTAGTGAGACACTGTAACTGTTTTTTTAAAAATCACTAA
+
+>hg17.chr7(+):127471526-127471584|sequence_index=0|block_index=1|species=hg17|hg17_1_0
+AATTTGTGGTTTATTCATTTTTCATTATTTTGTTTAAGGAGGTCTATAGTGGAAGAGG
+>mm7.chr6(+):28984886-28984940|sequence_index=0|block_index=1|species=mm7|mm7_1_0
+----AACGTTTCATTGATTGCTCATCATTTAAAAAAAGAAATTCCTCAGTGGAAGAGG
+>rheMac2.chr3(+):165788319-165788377|sequence_index=0|block_index=1|species=rheMac2|rheMac2_1_0
+AATTTGTGGTTTATTTATTTTTCATTATTTTGTTTAAGGAGGTCTATAGTGGAAGAGG
+>panTro1.chr6(+):129885407-129885465|sequence_index=0|block_index=1|species=panTro1|panTro1_1_0
+AATTTGTGGTTTATTCGTTTTTCATTATTTTGTTTAAGGAGGTCTATAGTGGAAGAGG
+
+>hg17.chr7(+):127471584-127471688|sequence_index=0|block_index=2|species=hg17|hg17_2_0
+GAGATATTT-GGggaaatttt-gtatagactagctt--tcacgatgttagggaattattattgtgtgataatggtcttgcagttac-acagaaattcttcctta-ttttt
+>panTro1.chr6(+):129885465-129885569|sequence_index=0|block_index=2|species=panTro1|panTro1_2_0
+GAGACATTT-GGggaaatttt-gtatagactagctt--tcacgatgttagggagttattattgtgtgataatggtcttgcagttac-acagaaattcttcctta-ttttt
+>rheMac2.chr3(+):165788377-165788482|sequence_index=0|block_index=2|species=rheMac2|rheMac2_2_0
+GAGATATTT-GGggaaatttg-gtatagactagctt--tcatgatgtaagggagttatttttgtgtgataatggccctacagttac-acagaaattcttccttatttttt
+>canFam2.chr14(-):11090703-11090811|sequence_index=0|block_index=2|species=canFam2|canFam2_2_0
+gagatattt-gggggaatttgaatgtagtgttgctcttttgtgatgctaagaaattataattgtctgatgatagtctcgtggttatgggggaaatgcttcctta-ttttt
+>bosTau2.chr4(-):50243931-50244034|sequence_index=0|block_index=2|species=bosTau2|bosTau2_2_0
+-agacattg-ggtaaaattcaaatgcagactagctc----atgatgttaaagaattactcttgtgtggtaatggtcttgtgatagagatagaaatgcttcctta-ttttt
+>rn3.chr4(+):56182200-56182295|sequence_index=0|block_index=2|species=rn3|rn3_2_0
+----TATTTGGGGGAAATATG-ATGTGCA----CTT--CCATGATCTTAAAGAATTGCTACTGTTTGATAGTGATCTTATGGTTAA-ATAAAAAAAAT--CTTA-GTTGT
+>dasNov1.scaffold_256527(+):298-392|sequence_index=0|block_index=2|species=dasNov1|dasNov1_2_0
+GAGACATTT-GGAGAAATTTG-----------Aatt--tcatgatgttaaggaattacttttgtatgatgatggtcttgtggctat-gtagaatttcttccgtg-tttta
+
+>hg17.chr7(+):127471688-127471871|sequence_index=0|block_index=3|species=hg17|hg17_3_0
+tgggaagcaccaaagta-------gggataaaatgtcatgatgtgtgcaatacactttaaaatgtttttgccaaaa----------taattaa-------------------------tgaagc--aaatatg---gaaaataataattattaaatctaggt-----gatgggtatattgtagttcactatagtattgcacacttttctgtatgtttaaatttttcattta--------------------------aaaa-
+>panTro1.chr6(+):129885569-129885752|sequence_index=0|block_index=3|species=panTro1|panTro1_3_0
+tgggaaacaccaaagta-------gggataaaatgtcatgatgtgtgcaatacgctttaaaatatttttgccaaaa----------taattaa-------------------------tgaagc--aaatatg---gaaaataataattattaaatctaggt-----gatgggtatattgtagttcactatagtattgcacacttttctgtatgtttaaaattttcattta--------------------------aaaa-
+>rheMac2.chr3(+):165788482-165788684|sequence_index=0|block_index=3|species=rheMac2|rheMac2_3_0
+tgggaagcacaaaagta-------gggataaaatgtcatgatgtgtacaatatgctttaaaatatttttgccaaaa----------taattaa-------------------------tgaagc--aaatatg---gaaaataataactgttaaatctaggt-----gttgggtatattgcagttcattatgttattgcacacttttctgtgtgtttaaaattttcatttaaaaatatgttttaaaaatg-------aaaa-
+>rn3.chr4(+):56182295-56182489|sequence_index=0|block_index=3|species=rn3|rn3_3_0
+TAGAAAATACTCAAATATTTAGGGGCGTGACAATGTCACAGTGTCTGCAATTTGCTTTAAAGATTTTT-----AAA----------TATTTAAAAAAGTTTTAATAATTTTGAAAAACTGAAGCTACACTATG---GGAAGTGGTAATTGTTACATATGGGT-----AATAAGTAT-----AATTCGTTATATTAT-------TTTTC------TTAGAATTTTTCATTTG--------------------------AAAA-
+>bosTau2.chr4(-):50243792-50243930|sequence_index=0|block_index=3|species=bosTau2|bosTau2_3_0
+agataaacacttaagtattta---aggatgaaacgccctgatgtttgtaatttgctttagaatattttagccaaaa----------gaattaa-------------------------tgatgc--aaatatg--caaaaagagta--cgttaaacctaa-----------------------------------------------------atttgCGATTttcattta--------------------------aaaa-
+>canFam2.chr14(-):11090345-11090505|sequence_index=0|block_index=3|species=canFam2|canFam2_3_0
+agacacaaactgaagtattta---aggatgaaatgtcatgatgtttgcaattggctttaaaatattttagccaaaa-----------agtaaa-------------------------tgaagc--AAATATG--GGAAGACAATAATCATTAAATCTAGGT-----GATGCATAC---------------------------TTTTCCATATGTTTGAAATTTTCATTTA--------------------------AAAA-
+>dasNov1.scaffold_256527(+):393-625|sequence_index=0|block_index=3|species=dasNov1|dasNov1_3_0
+agacgcatgctgaagcatgta---aggataaaatgtcgtggtgtttgtaatttattctaaaacattttagccaaaaacaaataaataaataaa-------------------------tgaagc--aaatatgggggaaatgtttaattgttaaatctagatttaacacggtatataccgtgcttcattatactagtctctacttttccatgtgtttgaaattttCATTAAAATGTTTGTTTGTTGTCTGTTTTAATGAAAT
+
+>hg17.chr7(+):127471871-127471910|sequence_index=0|block_index=4|species=hg17|hg17_4_0
+actttgagctagacaccaggctatgagcta-ggagcatag
+>rheMac2.chr3(+):165788684-165788723|sequence_index=0|block_index=4|species=rheMac2|rheMac2_4_0
+actttgagctagataccaggttatgagcta-ggagcatag
+>panTro1.chr6(+):129885752-129885791|sequence_index=0|block_index=4|species=panTro1|panTro1_4_0
+actttgagctagacaccaggctatgagcta-ggagcatag
+>bosTau2.chr4(-):50243734-50243773|sequence_index=0|block_index=4|species=bosTau2|bosTau2_4_0
+tcttcgtgcaacgcacggggctatcaatgt-gggatacag
+>canFam2.chr14(-):11090081-11090120|sequence_index=0|block_index=4|species=canFam2|canFam2_4_0
+ACATCAtgctagatcctggactatgagctg-ggtatatag
+>dasNov1.scaffold_256527(+):625-665|sequence_index=0|block_index=4|species=dasNov1|dasNov1_4_0
+CCTTTGTGCTAGCCACTGGGATGAAAGCTAGGGAACACAG
+
+>hg17.chr7(+):127471910-127472074|sequence_index=0|block_index=5|species=hg17|hg17_5_0
+caatgaccaa----------------------------------------------------------------------------------------------atagactcctaccaa-ctc-aaagaatgcacattctCTG-GGAAACATGTTTCCATTAGGAAGCCTCGAATGCAATGTGACTGTGGTCTCCAGGACCTG-TGTGATCCTGGCTTTTCCTGTTCCCTCCG---CATCATCACTGCAGGTGTGTTTTCCCAAG
+>panTro1.chr6(+):129885791-129885955|sequence_index=0|block_index=5|species=panTro1|panTro1_5_0
+caatgaccaa----------------------------------------------------------------------------------------------atagactcctaccaa-ctc-aaagaatgcacattctCTG-GGAAACATGTTTCCATTAGGAAGCCTCGAATGCAATGTGACTGTGGTCTCCAGGACATG-TGTGATCCTGGCTTTTCCTGTTCCCTCTG---CATCATCACTGCAGGTGTATTTTCCCAAG
+>rheMac2.chr3(+):165788723-165788885|sequence_index=0|block_index=5|species=rheMac2|rheMac2_5_0
+caatgaccaa----------------------------------------------------------------------------------------------atagacccctaccga-ctc-aaagaatgtacattctTTG-GGAAACATGTTTCCATCAGAAAATCTCAAATGCAATGTGACTGGGGTCTCCAGGACCTG-TGTGAGCCTGGCTTTTCCTGTTCCCTCCA---CATCATCACTGCAGGTGTATTTTCCC--G
+>mm7.chr6(+):28990714-28990875|sequence_index=0|block_index=5|species=mm7|mm7_5_0
+caaaaaccaa------------------------------------------------------------------------------------------------aaaaACCTATAGC-CTC-ACAGGGTGGGTTGTCTTTG-AGGAACATGCATCCGCTAGAAAGTCCCAAGTACACTATGACAGTTG--CCCAGGCCCCGCCTTAAACCTGGTTTTCCTGGTTTCTTTCA---CATCATTACCACGAATATATTTCCTCAAG
+>rn3.chr4(+):56183448-56183705|sequence_index=0|block_index=5|species=rn3|rn3_5_0
+--ATGACCAATATACACTGTTTACATGTATAGCATTGTGAATGGAGACATAAAAAGATAATCTAGCTTTGTGCTAGGTAGGTGCTGAGCTCTTAACAGTGCTGGGCAGAAACCTATAAC-CTC-ACAGGGTGGGTTGTCTTTG-AGGAGCGTGCTAACCCTAGGAAGTCTCAAATACAATGTGATGGTTGCCCCCAGGCACCACCTTGAACCTGGTCTTCCTGGTTTCTTTCA---CACCATTACCACAAATACATTTTCTCAGG
+>bosTau2.chr4(-):50243566-50243734|sequence_index=0|block_index=5|species=bosTau2|bosTau2_5_0
+atgtgaacaa---------------------------------------------------------------------------------------------aacggacccgtgtgggactcggcggagcacacagattttgcgggagCACGTTCCCGTTAGGAAGTCTCTGATGCAATACGACCGGTGCCTTCAGGACCTG-TG--AGGCTGACTTTCCTTA-CCCCTCCACACCATCATCAAGGCAGGTGTGATTTTCCAGG
+>canFam2.chr14(-):11089913-11090081|sequence_index=0|block_index=5|species=canFam2|canFam2_5_0
+cagtgaacaa---------------------------------------------------------------------------------------------aacagagccctgcagt-cttgatggagcacacaacctttg-gggaaCATGTTTCCATAAGAAAGTCTCCAATGTGATCTGA-TGGTGCCGCCAGGACCTA-TGTCAGCCTACCGTTCCATGTCCCCTCCACACCATCATCACTGCAGGTGTGTTTTCCCACA
+>dasNov1.scaffold_256527(+):665-786|sequence_index=0|block_index=5|species=dasNov1|dasNov1_5_0
+CAGTGAGCAA-----------------------------------------------------------------------------------------------CAGCCTGGCTCCGT-CC--GGGGGCCGCTCAGCAGCTC-GGGAGCGTGGAGACG---GGAAGTCTGTCACGCGATGCG-----------CTGGGCCCG------------CTGTTCCCGCCCCCCTCC---CCCC----------------TTTCCCAAG
+
+>hg17.chr7(+):127472074-127472258|sequence_index=0|block_index=6|species=hg17|hg17_6_0
+TTTTAAA------CATTTACCTTCCCAGTGGCCTTGCGTCTAGAGGAATCCCTGTATAGTGGT-ACATGAATATAACACATAACAAA-AATCATCTCTATGGTGTGTGTTGTTCCTGGGGTTCAattcagcaaatttt-ccc-tgggcacccatgtgttcttggcactggaaaagtaccgggactgaaacagtt
+>panTro1.chr6(+):129885955-129886139|sequence_index=0|block_index=6|species=panTro1|panTro1_6_0
+TTTTAAA------CATTTACCTTCCCAGTGGCCTTGCGTCTAGAGGAATCCCTGTATAGTGGT-ACATGAATATAACACATAACAAA-AATCATCTCTATGGTGTGTGTTGTTCCTGGGGTTCAattcagcaaatttt-tcc-tgggcacccatgtgttcttggcactggaaaagtaccgggactgaaacagtt
+>rheMac2.chr3(+):165788885-165789069|sequence_index=0|block_index=6|species=rheMac2|rheMac2_6_0
+TTTTAAA------CATTTACTCTCCCAGTAGCCTTGCATCTCGAGGAATCCCTGTATAGTGGT-ACATGAATATAACACATAACAAA-AATCATCTGTACGGTGTGTGTTGTTCCTGGGGTTCAattcagcaaatttt-tcc-tgggcacccctgtgttcttggcactggaaaagtaccaggacttaaatagta
+>mm7.chr6(+):28990875-28991025|sequence_index=0|block_index=6|species=mm7|mm7_6_0
+TTTAAAGAAAGTACCCCCTCCTTTCCAGT-GCCTCAAATCTAGAAGAATATTCATAGTGAAGT-GC------------------------ACAGCCGGGTGGTGCATGGTA-ATCTGGAAGTCACCTCTGCAAATCTT-TCC----------------TGTTGGTGCTGTGAAGGCACCAGGACTTCAAGAGTA
+>rn3.chr4(+):56183705-56183879|sequence_index=0|block_index=6|species=rn3|rn3_6_0
+TTTAAAAGAAGT-CCCACTCCTTTCCAGT-GCCCTAGATCTAGAAGCACATTCATAATGATGT-ACAC-----TAACCC----------GACAGCTGTGTGGTATATGGTA-TCCCGGAAGTCACCTCAGCAAACCTT-TCCCGGGGAACCTACATGGTGTTGGTGCTGTGAAGGTACCAGGTTGTCAAGGGTA
+>canFam2.chr14(-):11089743-11089913|sequence_index=0|block_index=6|species=canFam2|canFam2_6_0
+TTTTAAA------TATCTGC-TTCCCGGTGGCCTTGAGTCTAGAGGAGTCCCCCCACTATGGTGGCACTAATACTGAAGGTCAGAAATAATCAGTTCTGTGGTGCATGTTGCCCCTGAGGTTCTGTTCGGGAAACTTC-TTC-TGAGCAC----ATGCACCTGGCACTGCAAACGTACCAGGA-----------
+>dasNov1.scaffold_256527(+):786-964|sequence_index=0|block_index=6|species=dasNov1|dasNov1_6_0
+TTTTAAA------AATTTACCTTCCCAGTGGCGGTGAATCCGGAGGAATACGGAAACTGGGGC-GCACTACCATGACACGTGTCAAA-AATCAGTTCCGTGGTCCGTGGAGGGCCTGGGGTTC------GAAAATCTTGTCC-CGAGCACCCCCGTGCGCCTGGCACCGCGACAGTGACAGGACTGAAGCGTG-
+
+>hg17.chr7(+):127472258-127472280|sequence_index=0|block_index=7|species=hg17|hg17_7_0
+gatggccca-atccctgtcctct-
+>panTro1.chr6(+):129886139-129886161|sequence_index=0|block_index=7|species=panTro1|panTro1_7_0
+gatggccca-atccctgtcctct-
+>rheMac2.chr3(+):165789069-165789091|sequence_index=0|block_index=7|species=rheMac2|rheMac2_7_0
+gatggccca-atccctgtcctct-
+>mm7.chr6(+):28991025-28991048|sequence_index=0|block_index=7|species=mm7|mm7_7_0
+AATGGCAGAGGGCTCTGTTCTCT-
+>rn3.chr4(+):56183879-56183902|sequence_index=0|block_index=7|species=rn3|rn3_7_0
+AATGGCAGAGGCCCCTGTTCTCT-
+>canFam2.chr14(-):11089526-11089548|sequence_index=0|block_index=7|species=canFam2|canFam2_7_0
+GGAGACTTG-ATGCCTGCCTTCC-
+>dasNov1.scaffold_256527(+):964-987|sequence_index=0|block_index=7|species=dasNov1|dasNov1_7_0
+GACGGCCAG-ACCTCTGCCCTCGG
+
+>hg17.chr7(+):127472280-127472681|sequence_index=0|block_index=8|species=hg17|hg17_8_0
+taaaacctaagggaggagaTGGAAAG-GGGCACCCAACCCAGACTGAGAGACAGGAATTAGCTGCAAGGGGAACTAGGAAAAGCTTCTTTA---AGGATG--GAGAGGCCCTA-GTGGAATGGGGAGATTCTTCCGGGAGAAGCGATGGATGCACAGTTGGGCATCCCCACAGACGGACTGGAAAGAAAAAAGGCCTGGAGGAATCA------ATGTGC-AATGTATGTGTGTTCCCTGGTTcaagggctgg-gaactttctcta--aagggccaggtagaaaacattttaggctttctaagccaagg---caaaattgaggat-attacatgggtacttatacaacaagaataaacaatt---tacacaa-ttttttgttgacagaattcaaaa---ctttat----agacac---agaaatgcaaatttcctgt
+>panTro1.chr6(+):129886161-129886562|sequence_index=0|block_index=8|species=panTro1|panTro1_8_0
+taaaacctaagggaggagaTGGAAAG-GGGCACCCAACCCAGACTGAGAGACAGGAATTAGCTGCAAGGGGAACTAGGAAAAGCTTCTTTA---AGGATG--GAGAGACCCTA-GTGGAATGGGGAGATTCTTCCGGGAGAAGCGATGGATGCGCAGTTGGGCATCCCCACAGACGGACTGGAAAGAAAAAAGGCCTGGAGGAATCA------ATGTGC-AATGTATGTGTGTTCCCTGGTTcaagggctgg-gaactttctcta--aagggccaggtagaaaacattttaggctttctaagccaagg---caaaattgaggat-attacatgggtacttatacaacaagaataaacaatt---tacacaa-ttttttgttgacagaattcaaaa---ctttat----agacac---agaaatgtaaatttcctgt
+>rheMac2.chr3(+):165789091-165789492|sequence_index=0|block_index=8|species=rheMac2|rheMac2_8_0
+taaaacctaatggaggagatggaATG-GGTCACCCAACCCGGACTGAGAGACAGGAATTAGCTGCAAGGGTAACCAGGACAAGCTTCTCTA---ATGATG--GAGAGACCCTA-GTGGAATGGGGAGATTCTTCTGGGAGAAGCGATGGATTCGTAGTTGGGCATCCCCACAGAGGGACTGGAAAGAAAAAAGACCTGGAGGAACCA------ATGTGC-AATGTATGTGTGTTTCCTGGTTcaagggctggcaaactttctcta--aagggccagatagaaaacattttaggctttgtaagccaagg---caaaatcgaggag-attacatgggtacttatacaacaagaataaacaatt---tccacaa--tttttattcacagaattcaaaa---ctttat----agacac---agaaatgtaaatttcctgt
+>rn3.chr4(+):56183902-56184219|sequence_index=0|block_index=8|species=rn3|rn3_8_0
+------------------------------------GTCCATAGTCAAAG------------------------------AAGCCTCTCAG---ATGGAG--AGCAGGGCCTATGCAAAAGAGGGGGCTTCTGTAGGCAGAAGGGATGGACTAGCCTCCGGACATAGCCATAGAGAGGCTGGCAGGACTGAGACCCAGGAGAAGCCAGCGCAGGTGTGCGGGCGTGTGTATATTTCATAGTTTGCAGGTTGG----------------------------CAAACAATTCCTGCTTTGCAGGCCAAGA---GGAAACTGAAGGTGACCCCGTGAGTGCTTAC---ACAAGAGAAAACAAG-------ACAA-TTTTTGGTTGACCAAATTCAGAA---CTTTATTTGAGGATGC---TAAAGTTTAAATTTCTTTT
+>canFam2.chr14(-):11089143-11089523|sequence_index=0|block_index=8|species=canFam2|canFam2_8_0
+TACAGCCTGTGGGCAGAGGTGGGAAGAGGTCACGCAAGCCAGTTGGAATGAGGGGAGTTGGCTGGAAAGGTGACCAGGACAAGCTACTTCAACCAGGAAG--AAGAGACCCCG-GTG----------------CTTGGAGAAGGCCTGATTGAGCAGTCCTGCATGCCCGCCCAC-GACTGGCAGGAATAAAGACCCAGAAGAGCTA------ACGTGC-AATGTA------TTTTCTAGTTCCAgggttggcaaactttctctct-aagggtgggatgataaacattttaggcttttcagaccaaga---ggcgacatcagag-ggtatgtaggt---------acaagagggaaaagttgcccccggaa-ttttttg--gataaaattcaaaa---ctttacttagggatgc---caaaatgtaaacttcatat
+>dasNov1.scaffold_256527(+):987-1401|sequence_index=0|block_index=8|species=dasNov1|dasNov1_8_0
+CTAAATCTCGCGGAGAAGGTGGAACA-GGTTACCCAAACCCGACCGAG-GAGGCGAGTTG---GAAACGGCGACTGGGACAAGCTCCCTCA---GAGACGGAGAGAGACCCCA-GTGGAAGGGGGGAGAGGCTCTTAGGGAAACGATGGGGGGACCCGCCCGCACCCGCACAGAGGCGCTGGCAGGCACAGCGGCCCCGAGGAGCCC------AGGAGC-AGGGC-TGTGT-TCCCCTGCATcaggggttggcaaactttttctgcaaagggccagatagtaaatattttaggctttgcaaaccaagaagtagaaagggaggcc-attatgtacgtatttatatagcaagagagaacattt---cccacaatttttttattgacagaatttaaaacttctttattgatgaacaccaaagaaacttgaatttcatat
+
+>hg17.chr7(+):127472681-127472715|sequence_index=0|block_index=9|species=hg17|hg17_9_0
+aattttcccat---gagaactattcttcttttgtttt
+>rheMac2.chr3(+):165789492-165789526|sequence_index=0|block_index=9|species=rheMac2|rheMac2_9_0
+aattttcacat---aagaactattcttcttttgtttt
+>panTro1.chr6(+):129886562-129886596|sequence_index=0|block_index=9|species=panTro1|panTro1_9_0
+aattttcccgt---gagaactattcttcttttgtttt
+>canFam2.chr14(-):11089108-11089143|sequence_index=0|block_index=9|species=canFam2|canFam2_9_0
+aatggtcatgt--ccataactattcttcttttatttt
+>dasNov1.scaffold_256527(+):1401-1433|sequence_index=0|block_index=9|species=dasNov1|dasNov1_9_0
+aattttcacatatcacgaagtatttttttttt-----
+
diff -r eba44fc830bf -r c3b40f23a0e0 test-data/closest_features_either.interval
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/closest_features_either.interval Wed Sep 09 14:24:11 2009 -0400
@@ -0,0 +1,424 @@
+chr22 30128507 30133507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30136507 30141507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30132507 30137507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30140507 30145507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30136507 30141507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30128507 30133507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30140507 30145507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30132507 30137507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30144507 30149507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30136507 30141507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30148507 30153507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30140507 30145507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30152507 30157507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30144507 30149507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30156507 30161507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30148507 30153507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30160507 30165507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30152507 30157507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30164507 30169507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30156507 30161507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30168507 30173507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30160507 30165507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30172507 30177507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30164507 30169507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30176507 30181507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30168507 30173507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30180507 30185507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30172507 30177507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30184507 30189507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30176507 30181507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30188507 30193507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30180507 30185507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30192507 30197507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30184507 30189507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30196507 30201507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30188507 30193507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30200507 30205507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30192507 30197507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30204507 30209507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30196507 30201507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30208507 30213507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30200507 30205507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30212507 30217507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30204507 30209507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30216507 30221507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30208507 30213507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30220507 30225507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30212507 30217507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30224507 30229507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30216507 30221507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30228507 30233507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30220507 30225507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30232507 30237507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30224507 30229507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30236507 30241507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30228507 30233507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30240507 30245507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30232507 30237507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30244507 30249507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30236507 30241507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30248507 30253507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30240507 30245507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30252507 30257507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30244507 30249507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30256507 30261507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30248507 30253507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30260507 30265507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30252507 30257507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30264507 30269507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30256507 30261507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30268507 30273507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30260507 30265507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30272507 30277507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30264507 30269507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30276507 30281507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30268507 30273507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30280507 30285507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30272507 30277507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30284507 30289507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30276507 30281507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30288507 30293507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30280507 30285507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30292507 30297507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30284507 30289507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30296507 30301507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30288507 30293507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30300507 30305507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30292507 30297507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30304507 30309507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30296507 30301507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30308507 30313507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30300507 30305507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30312507 30317507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30304507 30309507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30316507 30321507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30308507 30313507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30320507 30325507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30312507 30317507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30324507 30329507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30316507 30321507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30328507 30333507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30320507 30325507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30332507 30337507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30324507 30329507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30336507 30341507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30328507 30333507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30340507 30345507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30332507 30337507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30344507 30349507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30336507 30341507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30348507 30353507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30340507 30345507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30352507 30357507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30344507 30349507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30356507 30361507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30348507 30353507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30360507 30365507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30352507 30357507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30364507 30369507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30356507 30361507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30368507 30373507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30360507 30365507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30372507 30377507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30364507 30369507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30376507 30381507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30368507 30373507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30380507 30385507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30372507 30377507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30384507 30389507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30376507 30381507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30388507 30393507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30380507 30385507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30392507 30397507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30384507 30389507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30396507 30401507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30388507 30393507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30400507 30405507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30392507 30397507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30404507 30409507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30396507 30401507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30408507 30413507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30400507 30405507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30412507 30417507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30404507 30409507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30416507 30421507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30408507 30413507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30420507 30425507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30412507 30417507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30424507 30429507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30416507 30421507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30428507 30433507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30420507 30425507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30432507 30437507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30424507 30429507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30436507 30441507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30428507 30433507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30440507 30445507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30432507 30437507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30444507 30449507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30436507 30441507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30448507 30453507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30440507 30445507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30452507 30457507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30444507 30449507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30456507 30461507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30448507 30453507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30460507 30465507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30452507 30457507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30464507 30469507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30456507 30461507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30468507 30473507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30460507 30465507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30472507 30477507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30464507 30469507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30476507 30481507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30468507 30473507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30480507 30485507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30472507 30477507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30484507 30489507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30476507 30481507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30488507 30493507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30480507 30485507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30492507 30497507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30484507 30489507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30496507 30501507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30488507 30493507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30500507 30505507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30492507 30497507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30504507 30509507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30496507 30501507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30508507 30513507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30500507 30505507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30512507 30517507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30504507 30509507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30516507 30521507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30508507 30513507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30520507 30525507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30512507 30517507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30524507 30529507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30516507 30521507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30528507 30533507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30520507 30525507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30532507 30537507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30524507 30529507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30536507 30541507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30528507 30533507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30540507 30545507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30532507 30537507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30544507 30549507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30536507 30541507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30548507 30553507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30540507 30545507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30552507 30557507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30544507 30549507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30556507 30561507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30548507 30553507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30560507 30565507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30552507 30557507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30564507 30569507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30556507 30561507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30568507 30573507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30560507 30565507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30572507 30577507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30564507 30569507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30576507 30581507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30568507 30573507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30580507 30585507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30572507 30577507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30584507 30589507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30576507 30581507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30588507 30593507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30580507 30585507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30592507 30597507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30584507 30589507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30596507 30601507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30588507 30593507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30600507 30605507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30592507 30597507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30604507 30609507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30596507 30601507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30608507 30613507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30600507 30605507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30612507 30617507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30604507 30609507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30616507 30621507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30608507 30613507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30620507 30625507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30612507 30617507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30624507 30629507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30616507 30621507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30628507 30633507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30620507 30625507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30632507 30637507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30624507 30629507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30636507 30641507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30628507 30633507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30640507 30645507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30632507 30637507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30644507 30649507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30636507 30641507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30648507 30653507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30640507 30645507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30652507 30657507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30644507 30649507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30656507 30661507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30648507 30653507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30660507 30665507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30652507 30657507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30664507 30669507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30656507 30661507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30668507 30673507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30660507 30665507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30672507 30677507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30664507 30669507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30676507 30681507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30668507 30673507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30680507 30685507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30672507 30677507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30684507 30689507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30676507 30681507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30688507 30693507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30680507 30685507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30692507 30697507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30684507 30689507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30696507 30701507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30688507 30693507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30700507 30705507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30692507 30697507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30704507 30709507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30696507 30701507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30708507 30713507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30700507 30705507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30712507 30717507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30704507 30709507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30716507 30721507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30708507 30713507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30720507 30725507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30712507 30717507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30724507 30729507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30716507 30721507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30728507 30733507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30720507 30725507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30732507 30737507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30724507 30729507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30736507 30741507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30728507 30733507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30740507 30745507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30732507 30737507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30744507 30749507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30736507 30741507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30748507 30753507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30740507 30745507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30752507 30757507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30744507 30749507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30756507 30761507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30748507 30753507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30760507 30765507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30752507 30757507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30764507 30769507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30756507 30761507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30768507 30773507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30760507 30765507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30772507 30777507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30764507 30769507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30776507 30781507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30768507 30773507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30780507 30785507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30772507 30777507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30784507 30789507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30776507 30781507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30788507 30793507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30780507 30785507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30792507 30797507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30784507 30789507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30796507 30801507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30788507 30793507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30800507 30805507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30792507 30797507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30804507 30809507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30796507 30801507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30808507 30813507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30800507 30805507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30812507 30817507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30804507 30809507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30816507 30821507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30808507 30813507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30820507 30825507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30812507 30817507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30824507 30829507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30816507 30821507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30828507 30833507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30820507 30825507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30832507 30837507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30824507 30829507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30836507 30841507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30828507 30833507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30840507 30845507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30832507 30837507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30844507 30849507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30836507 30841507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30848507 30853507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30840507 30845507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30852507 30857507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30844507 30849507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30856507 30861507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30848507 30853507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30860507 30865507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30852507 30857507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30864507 30869507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30856507 30861507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30868507 30873507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30860507 30865507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30872507 30877507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30864507 30869507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30876507 30881507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30868507 30873507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30880507 30885507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30872507 30877507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30884507 30889507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30876507 30881507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30888507 30893507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30880507 30885507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30892507 30897507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30884507 30889507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30896507 30901507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30888507 30893507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30900507 30905507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30892507 30897507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30904507 30909507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30896507 30901507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30908507 30913507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30900507 30905507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30912507 30917507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30904507 30909507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30916507 30921507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30908507 30913507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30920507 30925507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30912507 30917507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30924507 30929507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30916507 30921507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30928507 30933507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30920507 30925507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30932507 30937507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30924507 30929507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30936507 30941507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30928507 30933507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30940507 30945507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30932507 30937507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30944507 30949507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30936507 30941507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30948507 30953507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30940507 30945507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30952507 30957507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30944507 30949507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30956507 30961507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30948507 30953507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30960507 30965507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30952507 30957507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30964507 30969507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30956507 30961507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30968507 30973507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30960507 30965507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30972507 30977507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30964507 30969507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30976507 30981507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30968507 30973507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30980507 30985507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30972507 30977507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30984507 30989507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30976507 30981507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30988507 30993507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30980507 30985507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30992507 30997507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30984507 30989507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 30996507 31001507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30988507 30993507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31000507 31005507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30992507 30997507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31004507 31009507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 30996507 31001507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31008507 31013507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31000507 31005507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31012507 31017507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31004507 31009507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31016507 31021507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31008507 31013507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31020507 31025507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31012507 31017507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31024507 31029507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31016507 31021507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31028507 31033507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31020507 31025507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31032507 31037507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31024507 31029507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31036507 31041507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31028507 31033507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31040507 31045507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31032507 31037507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31044507 31049507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31036507 31041507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31048507 31053507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31040507 31045507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31052507 31057507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31044507 31049507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31056507 31061507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31048507 31053507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31060507 31065507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31052507 31057507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31064507 31069507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31056507 31061507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31068507 31073507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31060507 31065507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31072507 31077507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31064507 31069507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31076507 31081507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31068507 31073507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31080507 31085507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31072507 31077507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31084507 31089507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31076507 31081507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31088507 31093507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31080507 31085507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31092507 31097507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31084507 31089507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31096507 31101507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31088507 31093507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31100507 31105507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31092507 31097507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31104507 31109507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31096507 31101507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31108507 31113507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31100507 31105507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31112507 31117507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31104507 31109507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31116507 31121507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31108507 31113507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31120507 31125507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31112507 31117507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31124507 31129507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31116507 31121507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31128507 31133507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31120507 31125507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31132507 31137507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31124507 31129507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31136507 31141507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31128507 31133507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31140507 31145507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31132507 31137507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31144507 31149507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31136507 31141507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31148507 31153507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31140507 31145507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31152507 31157507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31144507 31149507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31156507 31161507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31148507 31153507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31160507 31165507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31152507 31157507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31164507 31169507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31156507 31161507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31168507 31173507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31160507 31165507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31172507 31177507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31164507 31169507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31176507 31181507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31168507 31173507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31180507 31185507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31172507 31177507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31184507 31189507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31176507 31181507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31188507 31193507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31180507 31185507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31192507 31197507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31184507 31189507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31196507 31201507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31188507 31193507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31200507 31205507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31192507 31197507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31204507 31209507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31196507 31201507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31208507 31213507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31200507 31205507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31212507 31217507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31204507 31209507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31216507 31221507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31208507 31213507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31220507 31225507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31212507 31217507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
+chr22 31224507 31229507 uc003bnx.1_cds_2_0_chr22_29227_f 0 + chr22 31216507 31221507 uc003bnx.1_cds_2_0_chr22_29227_f 0 +
1
0
09 Sep '09
details: http://www.bx.psu.edu/hg/galaxy/rev/30579f99ecb6
changeset: 2668:30579f99ecb6
user: Kanwei Li <kanwei(a)gmail.com>
date: Fri Sep 04 17:38:09 2009 -0400
description:
Fix workflow saving issue when no ajax call is active
1 file(s) affected in this change:
templates/workflow/editor.mako
diffs (71 lines):
diff -r 106ed169b440 -r 30579f99ecb6 templates/workflow/editor.mako
--- a/templates/workflow/editor.mako Mon Aug 31 17:19:33 2009 -0400
+++ b/templates/workflow/editor.mako Fri Sep 04 17:38:09 2009 -0400
@@ -46,6 +46,7 @@
// Globals
workflow = null;
canvas_manager = null;
+ active_ajax_call = false;
// jQuery onReady
$( function() {
@@ -104,6 +105,14 @@
}
});
}
+ });
+
+ // For autosave purposes
+ $(document).ajaxStart( function() {
+ active_ajax_call = true;
+ $(document).bind( "ajaxStop.global", function() {
+ active_ajax_call = false;
+ });
});
$(document).ajaxError( function ( e, x ) {
@@ -341,10 +350,14 @@
var save_current_workflow = function ( success_callback ) {
show_modal( "Saving workflow", "progress" );
workflow.check_changes_in_active_form();
- // We bind to ajaxStop because of auto-saving, since the form submission ajax
- // call needs to be completed so that the new data is saved
- $(document).bind('ajaxStop.save_workflow', function() {
- $(document).unbind('ajaxStop.save_workflow');
+ if (!workflow.has_changes) {
+ hide_modal();
+ if ( success_callback ) {
+ success_callback();
+ }
+ return;
+ }
+ var savefn = function() {
$.ajax( {
url: "${h.url_for( action='save_workflow' )}",
type: "POST",
@@ -379,8 +392,23 @@
}
}
});
- $(document).unbind('ajaxStop.save_workflow'); // IE7 needs it here
- });
+ }
+
+ // We bind to ajaxStop because of auto-saving, since the form submission ajax
+ // call needs to be completed so that the new data is saved
+ if (active_ajax_call) {
+ $(document).bind('ajaxStop.save_workflow', function() {
+ $(document).unbind('ajaxStop.save_workflow');
+ savefn();
+ $(document).unbind('ajaxStop.save_workflow'); // IE7 needs it here
+ active_ajax_call = false;
+ });
+ } else {
+ savefn();
+ }
+ if ( success_callback ) {
+ success_callback();
+ }
}
</script>
1
0
09 Sep '09
details: http://www.bx.psu.edu/hg/galaxy/rev/eba44fc830bf
changeset: 2669:eba44fc830bf
user: Kanwei Li <kanwei(a)gmail.com>
date: Tue Sep 08 17:33:38 2009 -0400
description:
Fix issue with updater in history.mako with frozen status indicators, improve JS coding consistency
2 file(s) affected in this change:
templates/dataset/edit_attributes.mako
templates/root/history.mako
diffs (277 lines):
diff -r 30579f99ecb6 -r eba44fc830bf templates/dataset/edit_attributes.mako
--- a/templates/dataset/edit_attributes.mako Fri Sep 04 17:38:09 2009 -0400
+++ b/templates/dataset/edit_attributes.mako Tue Sep 08 17:33:38 2009 -0400
@@ -9,44 +9,43 @@
<% user, user_roles = trans.get_user_and_roles() %>
<%def name="javascripts()">
- ## <!--[if lt IE 7]>
- ## <script type='text/javascript' src="/static/scripts/IE7.js"> </script>
- ## <![endif]-->
- ${h.js( "jquery", "galaxy.base", "jquery.autocomplete", "autocomplete_tagging" )}
- <script type="text/javascript">
- $( document ).ready( function() {
+ ## <!--[if lt IE 7]>
+ ## <script type='text/javascript' src="/static/scripts/IE7.js"> </script>
+ ## <![endif]-->
+ ${h.js( "jquery", "galaxy.base", "jquery.autocomplete", "autocomplete_tagging" )}
+ <script type="text/javascript">
+ $( document ).ready( function() {
// Set up autocomplete tagger.
<%
- ## Build string of tag name, values.
- tag_names_and_values = list()
- for tag in data.tags:
- tag_name = tag.user_tname
- tag_value = ""
- if tag.value is not None:
- tag_value = tag.user_value
- tag_names_and_values.append("\"" + tag_name + "\" : \"" + tag_value + "\"")
+ ## Build string of tag name, values.
+ tag_names_and_values = list()
+ for tag in data.tags:
+ tag_name = tag.user_tname
+ tag_value = ""
+ if tag.value is not None:
+ tag_value = tag.user_value
+ tag_names_and_values.append("\"" + tag_name + "\" : \"" + tag_value + "\"")
%>
- var options =
- {
- tags : {${", ".join(tag_names_and_values)}},
- tag_click_fn: function(tag) { /* Do nothing. */ },
- use_toggle_link: false,
- input_size: 30,
- in_form: true,
- <% encoded_data_id = trans.security.encode_id(data.id) %>
- ajax_autocomplete_tag_url: "${h.url_for( controller='tag', action='tag_autocomplete_data', id=encoded_data_id, item_type="hda" )}",
- ajax_add_tag_url: "${h.url_for( controller='tag', action='add_tag_async', id=encoded_data_id, item_type="hda" )}",
- ajax_delete_tag_url: "${h.url_for( controller='tag', action='remove_tag_async', id=encoded_data_id, item_type="hda" )}",
- delete_tag_img: "${h.url_for('/static/images/delete_tag_icon_gray.png')}",
- delete_tag_img_rollover: "${h.url_for('/static/images/delete_tag_icon_white.png')}",
- add_tag_img: "${h.url_for('/static/images/add_icon.png')}",
- add_tag_img_rollover: "${h.url_for('/static/images/add_icon_dark.png')}",
+ var options = {
+ tags : {${", ".join(tag_names_and_values)}},
+ tag_click_fn: function(tag) { /* Do nothing. */ },
+ use_toggle_link: false,
+ input_size: 30,
+ in_form: true,
+ <% encoded_data_id = trans.security.encode_id(data.id) %>
+ ajax_autocomplete_tag_url: "${h.url_for( controller='tag', action='tag_autocomplete_data', id=encoded_data_id, item_type="hda" )}",
+ ajax_add_tag_url: "${h.url_for( controller='tag', action='add_tag_async', id=encoded_data_id, item_type="hda" )}",
+ ajax_delete_tag_url: "${h.url_for( controller='tag', action='remove_tag_async', id=encoded_data_id, item_type="hda" )}",
+ delete_tag_img: "${h.url_for('/static/images/delete_tag_icon_gray.png')}",
+ delete_tag_img_rollover: "${h.url_for('/static/images/delete_tag_icon_white.png')}",
+ add_tag_img: "${h.url_for('/static/images/add_icon.png')}",
+ add_tag_img_rollover: "${h.url_for('/static/images/add_icon_dark.png')}",
};
% if trans.get_user() is not None:
- $("#dataset-tag-area").autocomplete_tagging(options);
- });
+ $("#dataset-tag-area").autocomplete_tagging(options);
% endif
- </script>
+});
+ </script>
</%def>
<%def name="datatype( dataset, datatypes )">
diff -r 30579f99ecb6 -r eba44fc830bf templates/root/history.mako
--- a/templates/root/history.mako Fri Sep 04 17:38:09 2009 -0400
+++ b/templates/root/history.mako Tue Sep 08 17:33:38 2009 -0400
@@ -74,105 +74,88 @@
});
// Updater
updater({
- %for i, data in enumerate( reversed( datasets ) ):
- %if data.visible and data.state not in [ "deleted", "empty", "error", "ok" ]:
- %if i > 0:
- ,
- %endif
- "${data.id}": "${data.state}"
- %endif
- %endfor
+ <% updateable = [data for data in reversed( datasets ) if data.visible and data.state not in [ "deleted", "empty", "error", "ok" ]] %>
+ ${ ",".join( map(lambda data: "\"%s\" : \"%s\"" % (data.id, data.state), updateable) ) }
});
- //
// Set up autocomplete tagger.
- //
<%
- ## Build string of tag name, values.
- tag_names_and_values = list()
- for tag in history.tags:
- tag_name = tag.user_tname
- tag_value = ""
- if tag.value is not None:
- tag_value = tag.user_value
- tag_names_and_values.append("\"" + tag_name + "\" : \"" + tag_value + "\"")
+ ## Build string of tag name, values.
+ tag_names_and_values = list()
+ for tag in history.tags:
+ tag_name = tag.user_tname
+ tag_value = ""
+ if tag.value is not None:
+ tag_value = tag.user_value
+ tag_names_and_values.append("\"" + tag_name + "\" : \"" + tag_value + "\"")
%>
- //
- // Returns the number of keys (elements) in an array/dictionary.
- //
- var array_length = function(an_array)
- {
- if (an_array.length)
- return an_array.length;
+ // Returns the number of keys (elements) in an array/dictionary.
+ var array_length = function(an_array)
+ {
+ if (an_array.length)
+ return an_array.length;
- var count = 0;
- for (element in an_array)
- count++;
- return count;
- };
+ var count = 0;
+ for (element in an_array)
+ count++;
+ return count;
+ };
- //
- // Function get text to display on the toggle link.
- //
- var get_toggle_link_text = function(tags)
- {
- var text = "";
- var num_tags = array_length(tags);
- if (num_tags != 0)
- {
- text = num_tags + (num_tags != 1 ? " Tags" : " Tag");
- /*
- // Show first N tags; hide the rest.
- var max_to_show = 1;
+ // Function get text to display on the toggle link.
+ var get_toggle_link_text = function(tags)
+ {
+ var text = "";
+ var num_tags = array_length(tags);
+ if (num_tags != 0) {
+ text = num_tags + (num_tags != 1 ? " Tags" : " Tag");
+ /*
+ // Show first N tags; hide the rest.
+ var max_to_show = 1;
- // Build tag string.
- var tag_strs = new Array();
- var count = 0;
- for (tag_name in tags)
- {
- tag_value = tags[tag_name];
- tag_strs[tag_strs.length] = build_tag_str(tag_name, tag_value);
- if (++count == max_to_show)
- break;
- }
- tag_str = tag_strs.join(", ");
-
- // Finalize text.
- var num_tags_hiding = num_tags - max_to_show;
- text = "Tags: " + tag_str +
- (num_tags_hiding != 0 ? " and " + num_tags_hiding + " more" : "");
- */
- }
- else
- {
- // No tags.
- text = "Add tags to this history";
- }
- return text;
- };
-
- var options =
- {
- tags : {${", ".join(tag_names_and_values)}},
- get_toggle_link_text_fn: get_toggle_link_text,
- input_size: 15,
- tag_click_fn: function(tag) { /* Do nothing. */ },
- <% encoded_history_id = trans.security.encode_id(history.id) %>
- ajax_autocomplete_tag_url: "${h.url_for( controller='tag', action='tag_autocomplete_data', id=encoded_history_id, item_type="history" )}",
- ajax_add_tag_url: "${h.url_for( controller='tag', action='add_tag_async', id=encoded_history_id, item_type="history" )}",
- ajax_delete_tag_url: "${h.url_for( controller='tag', action='remove_tag_async', id=encoded_history_id, item_type="history" )}",
- delete_tag_img: "${h.url_for('/static/images/delete_tag_icon_gray.png')}",
- delete_tag_img_rollover: "${h.url_for('/static/images/delete_tag_icon_white.png')}",
- add_tag_img: "${h.url_for('/static/images/add_icon.png')}",
- add_tag_img_rollover: "${h.url_for('/static/images/add_icon_dark.png')}",
- };
+ // Build tag string.
+ var tag_strs = new Array();
+ var count = 0;
+ for (tag_name in tags)
+ {
+ tag_value = tags[tag_name];
+ tag_strs[tag_strs.length] = build_tag_str(tag_name, tag_value);
+ if (++count == max_to_show)
+ break;
+ }
+ tag_str = tag_strs.join(", ");
+
+ // Finalize text.
+ var num_tags_hiding = num_tags - max_to_show;
+ text = "Tags: " + tag_str +
+ (num_tags_hiding != 0 ? " and " + num_tags_hiding + " more" : "");
+ */
+ } else {
+ // No tags.
+ text = "Add tags to this history";
+ }
+ return text;
+ };
+
+ var options = {
+ tags : {${", ".join(tag_names_and_values)}},
+ get_toggle_link_text_fn: get_toggle_link_text,
+ input_size: 15,
+ tag_click_fn: function(tag) { /* Do nothing. */ },
+ <% encoded_history_id = trans.security.encode_id(history.id) %>
+ ajax_autocomplete_tag_url: "${h.url_for( controller='tag', action='tag_autocomplete_data', id=encoded_history_id, item_type="history" )}",
+ ajax_add_tag_url: "${h.url_for( controller='tag', action='add_tag_async', id=encoded_history_id, item_type="history" )}",
+ ajax_delete_tag_url: "${h.url_for( controller='tag', action='remove_tag_async', id=encoded_history_id, item_type="history" )}",
+ delete_tag_img: "${h.url_for('/static/images/delete_tag_icon_gray.png')}",
+ delete_tag_img_rollover: "${h.url_for('/static/images/delete_tag_icon_white.png')}",
+ add_tag_img: "${h.url_for('/static/images/add_icon.png')}",
+ add_tag_img_rollover: "${h.url_for('/static/images/add_icon_dark.png')}",
+ };
% if trans.get_user() is not None:
- $("#history-tag-area").autocomplete_tagging(options);
+ $("#history-tag-area").autocomplete_tagging(options);
% endif
});
// Functionized so AJAX'd datasets can call them
-// Get shown/hidden state from cookie
function initShowHide() {
// Load saved state and show as neccesary
@@ -215,8 +198,7 @@
delete prefs[id];
$.jStore.store("history_expand_state", JSON.stringify(prefs));
}
- }
- else {
+ } else {
// Showing stuff here
body.slideDown( "fast", function() {
if ( $.browser.mozilla ) { peek.css( "overflow", "auto" ); }
@@ -326,8 +308,7 @@
});
if ( force_history_refresh ) {
parent.frames.galaxy_history.location.reload();
- }
- else {
+ } else {
// Keep going (if there are still any items to track)
updater( tracked_datasets );
}
1
0
09 Sep '09
details: http://www.bx.psu.edu/hg/galaxy/rev/106ed169b440
changeset: 2667:106ed169b440
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Mon Aug 31 17:19:33 2009 -0400
description:
Another pass on tagging: fixed queries and minor UI issues and reintroduced tagging fields to templates.
8 file(s) affected in this change:
lib/galaxy/model/__init__.py
lib/galaxy/tags/tag_handler.py
lib/galaxy/web/controllers/tag.py
static/scripts/autocomplete_tagging.js
static/scripts/packed/autocomplete_tagging.js
static/scripts/packed/galaxy.base.js
templates/dataset/edit_attributes.mako
templates/root/history.mako
diffs (316 lines):
diff -r d7a780065c91 -r 106ed169b440 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Sat Aug 29 12:08:35 2009 -0400
+++ b/lib/galaxy/model/__init__.py Mon Aug 31 17:19:33 2009 -0400
@@ -1155,7 +1155,7 @@
self.name = name
def __str__ ( self ):
- return "Tag(id=%s, type=%s, parent_id=%s, name=%s)" % ( self.id, self.type, self.parent_id, self.name )
+ return "Tag(id=%s, type=%i, parent_id=%s, name=%s)" % ( self.id, self.type, self.parent_id, self.name )
class ItemTagAssociation ( object ):
def __init__( self, item_id=None, tag_id=None, user_tname=None, value=None ):
diff -r d7a780065c91 -r 106ed169b440 lib/galaxy/tags/tag_handler.py
--- a/lib/galaxy/tags/tag_handler.py Sat Aug 29 12:08:35 2009 -0400
+++ b/lib/galaxy/tags/tag_handler.py Mon Aug 31 17:19:33 2009 -0400
@@ -45,7 +45,13 @@
del item.tags[:]
# Returns true if item is has a given tag.
- def item_has_tag(self, item, tag_name):
+ def item_has_tag(self, item, tag):
+ # Get tag name.
+ if isinstance(tag, basestring):
+ tag_name = tag
+ elif isinstance(tag, Tag):
+ tag_name = tag.name
+
# Check for an item-tag association to see if item has a given tag.
item_tag_assoc = self._get_item_tag_assoc(item, tag_name)
if item_tag_assoc:
@@ -103,11 +109,15 @@
if tag.value is not None:
tag_str += ":" + tag.user_value
tags_str_list.append(tag_str)
- return ", ".join(tags_str_list)
+ return ", ".join(tags_str_list)
- # Get a Tag object from a tag string.
- def _get_tag(self, db_session, tag_str):
- return db_session.query(Tag).filter(Tag.name==tag_str).first()
+ # Get a Tag object from a tag id.
+ def get_tag_by_id(self, db_session, tag_id):
+ return db_session.query(Tag).filter(Tag.id==tag_id).first()
+
+ # Get a Tag object from a tag name (string).
+ def get_tag_by_name(self, db_session, tag_name):
+ return db_session.query(Tag).filter(Tag.name==tag_name).first()
# Create a Tag object from a tag string.
def _create_tag(self, db_session, tag_str):
@@ -119,7 +129,7 @@
tag_name = tag_prefix + self._scrub_tag_name(sub_tag)
tag = db_session.query(Tag).filter(Tag.name==tag_name).first()
if not tag:
- tag = Tag(type="generic", name=tag_name)
+ tag = Tag(type=0, name=tag_name)
# Set tag parent.
tag.parent = parent_tag
@@ -137,7 +147,7 @@
return None
# Get item tag.
- tag = self._get_tag(db_session, scrubbed_tag_str)
+ tag = self.get_tag_by_name(db_session, scrubbed_tag_str)
# Create tag if necessary.
if tag is None:
diff -r d7a780065c91 -r 106ed169b440 lib/galaxy/web/controllers/tag.py
--- a/lib/galaxy/web/controllers/tag.py Sat Aug 29 12:08:35 2009 -0400
+++ b/lib/galaxy/web/controllers/tag.py Mon Aug 31 17:19:33 2009 -0400
@@ -63,10 +63,22 @@
@web.require_login( "get autocomplete data for an item's tags" )
def tag_autocomplete_data(self, trans, id=None, item_type=None, q=None, limit=None, timestamp=None):
""" Get autocomplete data for an item's tags. """
+
+ #
+ # Get item, do security check, and get autocomplete data.
+ #
item = self._get_item(trans, item_type, trans.security.decode_id(id))
self._do_security_check(trans, item)
+ if q.find(":") == -1:
+ return self._get_tag_autocomplete_names(trans, item, q, limit, timestamp)
+ else:
+ return self._get_tag_autocomplete_values(trans, item, q, limit, timestamp)
+
+ def _get_tag_autocomplete_names(self, trans, item, q, limit, timestamp):
+ """Returns autocomplete data for tag names ordered from most frequently used to
+ least frequently used."""
#
# Get user's item tags and usage counts.
#
@@ -75,55 +87,99 @@
item_tag_assoc_class = self.tag_handler.get_tag_assoc_class(item.__class__)
# Build select statement.
- cols_to_select = [ item_tag_assoc_class.table.c.tag_id, item_tag_assoc_class.table.c.user_tname, item_tag_assoc_class.table.c.user_value, func.count('*') ]
+ cols_to_select = [ item_tag_assoc_class.table.c.tag_id, func.count('*') ]
from_obj = item_tag_assoc_class.table.join(item.table).join(Tag)
- where_clause = self._get_column_for_filtering_item_by_user_id(item)==trans.get_user().id
+ where_clause = and_(self._get_column_for_filtering_item_by_user_id(item.__class__)==trans.get_user().id,
+ Tag.table.c.name.like(q + "%"))
order_by = [ func.count("*").desc() ]
- ac_for_names = not q.endswith(":")
- if ac_for_names:
- # Autocomplete for tag names.
- where_clause = and_(where_clause, Tag.table.c.name.like(q + "%"))
- group_by = item_tag_assoc_class.table.c.tag_id
- else:
- # Autocomplete for tag values.
- tag_name_and_value = q.split(":")
- tag_name = tag_name_and_value[0]
- tag_value = tag_name_and_value[1]
- where_clause = and_(where_clause, Tag.table.c.name==tag_name)
- where_clause = and_(where_clause, item_tag_assoc_class.table.c.value.like(tag_value + "%"))
- group_by = item_tag_assoc_class.table.c.value
+ group_by = item_tag_assoc_class.table.c.tag_id
# Do query and get result set.
query = select(columns=cols_to_select, from_obj=from_obj,
- whereclause=where_clause, group_by=group_by, order_by=order_by)
+ whereclause=where_clause, group_by=group_by, order_by=order_by, limit=limit)
result_set = trans.sa_session.execute(query)
# Create and return autocomplete data.
- if ac_for_names:
- # Autocomplete for tag names.
- ac_data = "#Header|Your Tags\n"
- for row in result_set:
- # Exclude tags that are already applied to the history.
- if self.tag_handler.item_has_tag(item, row[1]):
- continue
- # Add tag to autocomplete data.
- ac_data += row[1] + "|" + row[1] + "\n"
- else:
- # Autocomplete for tag values.
- ac_data = "#Header|Your Values for '%s'\n" % (tag_name)
- for row in result_set:
- ac_data += tag_name + ":" + row[2] + "|" + row[2] + "\n"
+ ac_data = "#Header|Your Tags\n"
+ for row in result_set:
+ tag = self.tag_handler.get_tag_by_id(trans.sa_session, row[0])
+ # Exclude tags that are already applied to the history.
+ if self.tag_handler.item_has_tag(item, tag):
+ continue
+ # Add tag to autocomplete data. Use the most frequent name that user
+ # has employed for the tag.
+ tag_names = self._get_usernames_for_tag(trans.sa_session, trans.get_user(),
+ tag, item.__class__, item_tag_assoc_class)
+ ac_data += tag_names[0] + "|" + tag_names[0] + "\n"
+
+ return ac_data
+
+ def _get_tag_autocomplete_values(self, trans, item, q, limit, timestamp):
+ """Returns autocomplete data for tag values ordered from most frequently used to
+ least frequently used."""
+
+ tag_name_and_value = q.split(":")
+ tag_name = tag_name_and_value[0]
+ tag_value = tag_name_and_value[1]
+ tag = self.tag_handler.get_tag_by_name(trans.sa_session, tag_name)
+ # Don't autocomplete if tag doesn't exist.
+ if tag is None:
+ return ""
+
+ # Get item-tag association class.
+ item_tag_assoc_class = self.tag_handler.get_tag_assoc_class(item.__class__)
+
+ # Build select statement.
+ cols_to_select = [ item_tag_assoc_class.table.c.value, func.count('*') ]
+ from_obj = item_tag_assoc_class.table.join(item.table).join(Tag)
+ where_clause = and_(self._get_column_for_filtering_item_by_user_id(item.__class__)==trans.get_user().id,
+ Tag.table.c.id==tag.id,
+ item_tag_assoc_class.table.c.value.like(tag_value + "%"))
+ order_by = [ func.count("*").desc(), item_tag_assoc_class.table.c.value ]
+ group_by = item_tag_assoc_class.table.c.value
+
+ # Do query and get result set.
+ query = select(columns=cols_to_select, from_obj=from_obj,
+ whereclause=where_clause, group_by=group_by, order_by=order_by, limit=limit)
+ result_set = trans.sa_session.execute(query)
+
+ # Create and return autocomplete data.
+ ac_data = "#Header|Your Values for '%s'\n" % (tag_name)
+ for row in result_set:
+ ac_data += tag.name + ":" + row[0] + "|" + row[0] + "\n"
return ac_data
- def _get_column_for_filtering_item_by_user_id(self, item):
+ def _get_usernames_for_tag(self, db_session, user, tag, item_class, item_tag_assoc_class):
+ """ Returns an ordered list of the user names for a tag; list is ordered from
+ most popular to least popular name."""
+
+ # Build select stmt.
+ cols_to_select = [ item_tag_assoc_class.table.c.user_tname, func.count('*') ]
+ where_clause = and_(self._get_column_for_filtering_item_by_user_id(item_class)==user.id ,
+ item_tag_assoc_class.table.c.tag_id==tag.id)
+ group_by = item_tag_assoc_class.table.c.user_tname
+ order_by = [ func.count("*").desc() ]
+
+ # Do query and get result set.
+ query = select(columns=cols_to_select, whereclause=where_clause,
+ group_by=group_by, order_by=order_by)
+ result_set = db_session.execute(query)
+
+ user_tag_names = list()
+ for row in result_set:
+ user_tag_names.append(row[0])
+
+ return user_tag_names
+
+ def _get_column_for_filtering_item_by_user_id(self, item_class):
""" Returns the column to use when filtering by user id. """
- if isinstance(item, History):
- return item.table.c.user_id
- elif isinstance(item, HistoryDatasetAssociation):
+ # TODO: make this generic by using a dict() to map from item class to a "user id" column
+ if item_class is History:
+ return History.table.c.user_id
+ elif item_class is HistoryDatasetAssociation:
# Use the user_id associated with the HDA's history.
- history = item.history
- return history.table.c.user_id
+ return History.table.c.user_id
def _get_item(self, trans, item_type, id):
""" Get an item based on type and id. """
diff -r d7a780065c91 -r 106ed169b440 static/scripts/autocomplete_tagging.js
--- a/static/scripts/autocomplete_tagging.js Sat Aug 29 12:08:35 2009 -0400
+++ b/static/scripts/autocomplete_tagging.js Mon Aug 31 17:19:33 2009 -0400
@@ -379,9 +379,17 @@
// When the tag area blurs, go to "view tag" mode.
tag_area.blur( function(e)
{
- add_tag_button.show();
- tag_input_field.hide();
- tag_area.removeClass("active-tag-area");
+ num_tags = array_length(settings.tags);
+ if (num_tags != 0)
+ {
+ add_tag_button.show();
+ tag_input_field.hide();
+ tag_area.removeClass("active-tag-area");
+ }
+ else
+ {
+ // No tags, so do nothing to ensure that input is still visible.
+ }
});
tag_area.append(add_tag_button);
diff -r d7a780065c91 -r 106ed169b440 static/scripts/packed/autocomplete_tagging.js
--- a/static/scripts/packed/autocomplete_tagging.js Sat Aug 29 12:08:35 2009 -0400
+++ b/static/scripts/packed/autocomplete_tagging.js Mon Aug 31 17:19:33 2009 -0400
@@ -1,1 +1,1 @@
-var ac_tag_area_id_gen=1;jQuery.fn.autocomplete_tagging=function(c){var e={get_toggle_link_text_fn:function(u){var w="";var v=o(u);if(v!=0){w=v+(v!=0?" Tags":" Tag")}else{w="Add tags"}return w},tag_click_fn:function(u){},input_size:20,in_form:false,tags:{},use_toggle_link:true,item_id:"",add_tag_img:"",add_tag_img_rollover:"",delete_tag_img:"",ajax_autocomplete_tag_url:"",ajax_retag_url:"",ajax_delete_tag_url:"",ajax_add_tag_url:""};var p=jQuery.extend(e,c);var k="tag-area-"+(ac_tag_area_id_gen)++;var m=$("<div></div>").attr("id",k).addClass("tag-area");this.append(m);var o=function(u){if(u.length){return u.length}var v=0;for(element in u){v++}return v};var b=function(){var u=p.get_toggle_link_text_fn(p.tags);var v=$("<a href='/history/tags'>"+u+"</a>").addClass("toggle-link");v.click(function(){var w=(m.css("display")=="none");var x;if(w){x=function(){var y=o(p.tags);if(y==0){m.click()}}}else{x=function(){m.blur()}}m.slideToggle("fast",x);return false});return v};var s=b();
if(p.use_toggle_link){this.prepend(s)}var t=function(u){var v=new Array();for(key in u){v[v.length]=key+"-->"+u[key]}return"{"+v.join(",")+"}"};var a=function(v,u){return v+((u!=""&&u)?":"+u:"")};var h=function(u){return u.split(":")};var i=function(u){var v=$("<img src='"+p.add_tag_img+"' rollover='"+p.add_tag_img_rollover+"'/>").addClass("add-tag-button");v.click(function(){$(this).hide();m.click();return false});return v};var j=function(u){var v=$("<img src='"+p.delete_tag_img+"'/>").addClass("delete-tag-img");v.mouseenter(function(){$(this).attr("src",p.delete_tag_img_rollover)});v.mouseleave(function(){$(this).attr("src",p.delete_tag_img)});v.click(function(){var B=$(this).parent();var A=B.find(".tag-name").eq(0);var z=A.text();var C=h(z)[0];B.remove();delete p.tags[C];var y=p.get_toggle_link_text_fn(p.tags);s.text(y);$.ajax({url:p.ajax_delete_tag_url,data:{tag_name:C},error:function(){alert("Remove tag failed")},success:function(){}});return true});var w=$("<span>"+u+"
</span>").addClass("tag-name");w.click(function(){p.tag_click_fn(u);return true});var x=$("<span></span>").addClass("tag-button");x.append(w);x.append(v);return x};var d=function(v){var u;if(p.in_form){u=$("<textarea id='history-tag-input' rows='1' cols='"+p.input_size+"' value='"+v+"'></textarea>")}else{u=$("<input id='history-tag-input' type='text' size='"+p.input_size+"' value='"+v+"'></input>")}u.keyup(function(D){if(D.keyCode==27){$(this).trigger("blur")}else{if((D.keyCode==13)||(D.keyCode==188)||(D.keyCode==32)){new_value=this.value;if(return_key_pressed_for_autocomplete==true){return_key_pressed_for_autocomplete=false;return false}if(new_value.indexOf(": ",new_value.length-2)!=-1){this.value=new_value.substring(0,new_value.length-1);return false}if((D.keyCode==188)||(D.keyCode==32)){new_value=new_value.substring(0,new_value.length-1)}new_value=new_value.replace(/^\s+|\s+$/g,"");if(new_value.length<3){return false}this.value="";var A=j(new_value);var z=m.children(".tag
-button");if(z.length!=0){var E=z.slice(z.length-1);E.after(A)}else{m.prepend(A)}var y=new_value.split(":");p.tags[y[0]]=y[1];var B=p.get_toggle_link_text_fn(p.tags);s.text(B);var C=$(this);$.ajax({url:p.ajax_add_tag_url,data:{new_tag:new_value},error:function(){A.remove();var F=p.get_toggle_link_text_fn(p.tags);s.text(F);alert("Add tag failed")},success:function(){C.flushCache()}});return false}}});var w=function(A,z,y,C,B){tag_name_and_value=C.split(":");return(tag_name_and_value.length==1?tag_name_and_value[0]:tag_name_and_value[1])};var x={selectFirst:false,formatItem:w,autoFill:false,highlight:false};u.autocomplete(p.ajax_autocomplete_tag_url,x);u.addClass("tag-input");return u};for(tag_name in p.tags){var q=p.tags[tag_name];var l=a(tag_name,q);var g=j(l,s,p.tags);m.append(g)}var n=d("");var f=i(n);m.blur(function(u){f.show();n.hide();m.removeClass("active-tag-area")});m.append(f);m.append(n);n.hide();m.click(function(w){var v=$(this).hasClass("active-tag-area");if($(w.
target).hasClass("delete-tag-img")&&!v){return false}if($(w.target).hasClass("tag-name")&&!v){return false}$(this).addClass("active-tag-area");f.hide();n.show();n.focus();var u=function(y){var x=m.attr("id");if(($(y.target).attr("id")!=x)&&($(y.target).parents().filter(x).length==0)){m.blur();$(document).unbind("click",u)}};$(window).click(u);return false});if(p.use_toggle_link){m.hide()}else{var r=o(p.tags);if(r==0){f.hide();n.show()}}return this.addClass("tag-element")};
\ No newline at end of file
+var ac_tag_area_id_gen=1;jQuery.fn.autocomplete_tagging=function(c){var e={get_toggle_link_text_fn:function(u){var w="";var v=o(u);if(v!=0){w=v+(v!=0?" Tags":" Tag")}else{w="Add tags"}return w},tag_click_fn:function(u){},input_size:20,in_form:false,tags:{},use_toggle_link:true,item_id:"",add_tag_img:"",add_tag_img_rollover:"",delete_tag_img:"",ajax_autocomplete_tag_url:"",ajax_retag_url:"",ajax_delete_tag_url:"",ajax_add_tag_url:""};var p=jQuery.extend(e,c);var k="tag-area-"+(ac_tag_area_id_gen)++;var m=$("<div></div>").attr("id",k).addClass("tag-area");this.append(m);var o=function(u){if(u.length){return u.length}var v=0;for(element in u){v++}return v};var b=function(){var u=p.get_toggle_link_text_fn(p.tags);var v=$("<a href='/history/tags'>"+u+"</a>").addClass("toggle-link");v.click(function(){var w=(m.css("display")=="none");var x;if(w){x=function(){var y=o(p.tags);if(y==0){m.click()}}}else{x=function(){m.blur()}}m.slideToggle("fast",x);return false});return v};var s=b();
if(p.use_toggle_link){this.prepend(s)}var t=function(u){var v=new Array();for(key in u){v[v.length]=key+"-->"+u[key]}return"{"+v.join(",")+"}"};var a=function(v,u){return v+((u!=""&&u)?":"+u:"")};var h=function(u){return u.split(":")};var i=function(u){var v=$("<img src='"+p.add_tag_img+"' rollover='"+p.add_tag_img_rollover+"'/>").addClass("add-tag-button");v.click(function(){$(this).hide();m.click();return false});return v};var j=function(u){var v=$("<img src='"+p.delete_tag_img+"'/>").addClass("delete-tag-img");v.mouseenter(function(){$(this).attr("src",p.delete_tag_img_rollover)});v.mouseleave(function(){$(this).attr("src",p.delete_tag_img)});v.click(function(){var B=$(this).parent();var A=B.find(".tag-name").eq(0);var z=A.text();var C=h(z)[0];B.remove();delete p.tags[C];var y=p.get_toggle_link_text_fn(p.tags);s.text(y);$.ajax({url:p.ajax_delete_tag_url,data:{tag_name:C},error:function(){alert("Remove tag failed")},success:function(){}});return true});var w=$("<span>"+u+"
</span>").addClass("tag-name");w.click(function(){p.tag_click_fn(u);return true});var x=$("<span></span>").addClass("tag-button");x.append(w);x.append(v);return x};var d=function(v){var u;if(p.in_form){u=$("<textarea id='history-tag-input' rows='1' cols='"+p.input_size+"' value='"+v+"'></textarea>")}else{u=$("<input id='history-tag-input' type='text' size='"+p.input_size+"' value='"+v+"'></input>")}u.keyup(function(D){if(D.keyCode==27){$(this).trigger("blur")}else{if((D.keyCode==13)||(D.keyCode==188)||(D.keyCode==32)){new_value=this.value;if(return_key_pressed_for_autocomplete==true){return_key_pressed_for_autocomplete=false;return false}if(new_value.indexOf(": ",new_value.length-2)!=-1){this.value=new_value.substring(0,new_value.length-1);return false}if((D.keyCode==188)||(D.keyCode==32)){new_value=new_value.substring(0,new_value.length-1)}new_value=new_value.replace(/^\s+|\s+$/g,"");if(new_value.length<3){return false}this.value="";var A=j(new_value);var z=m.children(".tag
-button");if(z.length!=0){var E=z.slice(z.length-1);E.after(A)}else{m.prepend(A)}var y=new_value.split(":");p.tags[y[0]]=y[1];var B=p.get_toggle_link_text_fn(p.tags);s.text(B);var C=$(this);$.ajax({url:p.ajax_add_tag_url,data:{new_tag:new_value},error:function(){A.remove();var F=p.get_toggle_link_text_fn(p.tags);s.text(F);alert("Add tag failed")},success:function(){C.flushCache()}});return false}}});var w=function(A,z,y,C,B){tag_name_and_value=C.split(":");return(tag_name_and_value.length==1?tag_name_and_value[0]:tag_name_and_value[1])};var x={selectFirst:false,formatItem:w,autoFill:false,highlight:false};u.autocomplete(p.ajax_autocomplete_tag_url,x);u.addClass("tag-input");return u};for(tag_name in p.tags){var q=p.tags[tag_name];var l=a(tag_name,q);var g=j(l,s,p.tags);m.append(g)}var n=d("");var f=i(n);m.blur(function(u){r=o(p.tags);if(r!=0){f.show();n.hide();m.removeClass("active-tag-area")}else{}});m.append(f);m.append(n);n.hide();m.click(function(w){var v=$(this).hasClas
s("active-tag-area");if($(w.target).hasClass("delete-tag-img")&&!v){return false}if($(w.target).hasClass("tag-name")&&!v){return false}$(this).addClass("active-tag-area");f.hide();n.show();n.focus();var u=function(y){var x=m.attr("id");if(($(y.target).attr("id")!=x)&&($(y.target).parents().filter(x).length==0)){m.blur();$(document).unbind("click",u)}};$(window).click(u);return false});if(p.use_toggle_link){m.hide()}else{var r=o(p.tags);if(r==0){f.hide();n.show()}}return this.addClass("tag-element")};
\ No newline at end of file
diff -r d7a780065c91 -r 106ed169b440 static/scripts/packed/galaxy.base.js
--- a/static/scripts/packed/galaxy.base.js Sat Aug 29 12:08:35 2009 -0400
+++ b/static/scripts/packed/galaxy.base.js Mon Aug 31 17:19:33 2009 -0400
@@ -1,1 +1,1 @@
-$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};jQuery(document).ready(function(){jQuery("a[confirm]").click(function(){return confirm(jQuery(this).attr("confirm"))});jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.show()})});function ensure_popup_helper(){if($("#popup-helper").length==0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_popupmenu(d,c){ens
ure_popup_helper();var a=$(d);var b=$("<ul id='"+d.attr("id")+"-menu'></div>");$.each(c,function(g,f){if(f){$("<li/>").html(g).click(f).appendTo(b)}else{$("<li class='head'/>").html(g).appendTo(b)}});var e=$("<div class='popmenu-wrapper'>");e.append(b).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(d,e)}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){var h=$(b).offset();$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)};
\ No newline at end of file
+$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};jQuery(document).ready(function(){jQuery("a[confirm]").click(function(){return confirm(jQuery(this).attr("confirm"))});jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.show()})});function ensure_popup_helper(){if($("#popup-helper").length==0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_popupmenu(d,c){ens
ure_popup_helper();var a=$(d);var b=$("<ul id='"+d.attr("id")+"-menu'></ul>");$.each(c,function(g,f){if(f){$("<li/>").html(g).click(f).appendTo(b)}else{$("<li class='head'/>").html(g).appendTo(b)}});var e=$("<div class='popmenu-wrapper'>");e.append(b).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(d,e)}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){var h=$(b).offset();$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)};
\ No newline at end of file
diff -r d7a780065c91 -r 106ed169b440 templates/dataset/edit_attributes.mako
--- a/templates/dataset/edit_attributes.mako Sat Aug 29 12:08:35 2009 -0400
+++ b/templates/dataset/edit_attributes.mako Mon Aug 31 17:19:33 2009 -0400
@@ -84,17 +84,17 @@
</div>
<div style="clear: both"></div>
</div>
- ## %if trans.get_user() is not None:
- ## <div class="form-row">
- ## <label>
- ## Tags:
- ## </label>
- ## <div id="dataset-tag-area"
- ## style="float: left; margin-left: 1px; width: 295px; margin-right: 10px; border-style: inset; border-color: #ddd; border-width: 1px">
- ## </div>
- ## <div style="clear: both"></div>
- ## </div>
- ## %endif
+ %if trans.get_user() is not None:
+ <div class="form-row">
+ <label>
+ Tags:
+ </label>
+ <div id="dataset-tag-area"
+ style="float: left; margin-left: 1px; width: 295px; margin-right: 10px; border-style: inset; border-color: #ddd; border-width: 1px">
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ %endif
%for name, spec in data.metadata.spec.items():
%if spec.visible:
<div class="form-row">
diff -r d7a780065c91 -r 106ed169b440 templates/root/history.mako
--- a/templates/root/history.mako Sat Aug 29 12:08:35 2009 -0400
+++ b/templates/root/history.mako Mon Aug 31 17:19:33 2009 -0400
@@ -377,8 +377,8 @@
<p></p>
%endif
-## <div id="history-tag-area" style="margin-bottom: 1em">
-## </div>
+<div id="history-tag-area" style="margin-bottom: 1em">
+</div>
<%namespace file="history_common.mako" import="render_dataset" />
1
0
09 Sep '09
details: http://www.bx.psu.edu/hg/galaxy/rev/4dfa7fd53a0c
changeset: 2664:4dfa7fd53a0c
user: Dan Blankenberg <dan(a)bx.psu.edu>
date: Fri Sep 04 11:08:10 2009 -0400
description:
Fix heading for Example 2 in maf_split_by_species onscreen tool help.
1 file(s) affected in this change:
tools/maf/maf_split_by_species.xml
diffs (12 lines):
diff -r 5d92863c4860 -r 4dfa7fd53a0c tools/maf/maf_split_by_species.xml
--- a/tools/maf/maf_split_by_species.xml Fri Sep 04 10:49:02 2009 -0400
+++ b/tools/maf/maf_split_by_species.xml Fri Sep 04 11:08:10 2009 -0400
@@ -116,7 +116,7 @@
-----
-**Example 1**: **Collapse empty alignment columns is Yes**:
+**Example 2**: **Collapse empty alignment columns is No**:
For the following alignment::
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/9bbf66f38265
changeset: 2665:9bbf66f38265
user: Dan Blankenberg <dan(a)bx.psu.edu>
date: Wed Sep 09 10:08:29 2009 -0400
description:
Fix implicit maf to fasta converter
1 file(s) affected in this change:
lib/galaxy/datatypes/converters/maf_to_fasta_converter.py
diffs (16 lines):
diff -r 4dfa7fd53a0c -r 9bbf66f38265 lib/galaxy/datatypes/converters/maf_to_fasta_converter.py
--- a/lib/galaxy/datatypes/converters/maf_to_fasta_converter.py Fri Sep 04 11:08:10 2009 -0400
+++ b/lib/galaxy/datatypes/converters/maf_to_fasta_converter.py Wed Sep 09 10:08:29 2009 -0400
@@ -30,12 +30,3 @@
if __name__ == "__main__": __main__()
-
- for component in block.components:
- spec, chrom = maf_utilities.src_split( component.src )
- if spec not in spec_counts:
- spec_counts[ spec ] = 0
- else:
- spec_counts[ spec ] += 1
- file_out.write( "%s\n" % maf_utilities.get_fasta_header( component, { 'block_index' : block_num, 'species' : spec, 'sequence_index' : spec_counts[ spec ] }, suffix = "%s_%i_%i" % ( spec, block_num, spec_counts[ spec ] ) ) )
- file_out.write( "%s\n" % component.text )
1
0