diff --git a/datatypes_conf.xml.sample b/datatypes_conf.xml.sample
index 8c6548f4728..cb49a79ce73 100644
--- a/datatypes_conf.xml.sample
+++ b/datatypes_conf.xml.sample
@@ -1,211 +1,224 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dist-eggs.ini b/dist-eggs.ini
index 93c1a7044e1..d9135c2a0bb 100644
--- a/dist-eggs.ini
+++ b/dist-eggs.ini
@@ -23,6 +23,9 @@ py2.4-macosx-10.3-fat-ucs2 = medeski.bx.psu.edu /usr/local/bin/python2.4
py2.5-macosx-10.3-fat-ucs2 = medeski.bx.psu.edu /usr/local/bin/python2.5
py2.6-macosx-10.3-fat-ucs2 = medeski.bx.psu.edu /usr/local/bin/python2.6
py2.5-macosx-10.5-i386-ucs2 = lion.bx.psu.edu /usr/bin/python2.5
+py2.4-solaris-2.10-i86pc-ucs2 = thumper.bx.psu.edu /depot/projects/pythons/solaris-2.10-i86pc-ucs2/bin/python2.4
+py2.5-solaris-2.10-i86pc-ucs2 = thumper.bx.psu.edu /depot/projects/pythons/solaris-2.10-i86pc-ucs2/bin/python2.5
+py2.6-solaris-2.10-i86pc-ucs2 = thumper.bx.psu.edu /depot/projects/pythons/solaris-2.10-i86pc-ucs2/bin/python2.6
py2.4-solaris-2.11-i86pc-ucs2 = victory.bx.psu.edu /depot/projects/pythons/solaris-2.11-i86pc-ucs2/bin/python2.4
py2.5-solaris-2.11-i86pc-ucs2 = victory.bx.psu.edu /depot/projects/pythons/solaris-2.11-i86pc-ucs2/bin/python2.5
py2.6-solaris-2.11-i86pc-ucs2 = victory.bx.psu.edu /depot/projects/pythons/solaris-2.11-i86pc-ucs2/bin/python2.6
@@ -47,9 +50,9 @@ py2.4-macosx = py2.4-macosx-10.3-fat-ucs2
py2.5-macosx = py2.5-macosx-10.3-fat-ucs2 py2.5-macosx-10.5-i386-ucs2
py2.6-macosx = py2.6-macosx-10.3-fat-ucs2
macosx = py2.4-macosx py2.5-macosx py2.6-macosx
-py2.4-solaris = py2.4-solaris-2.11-i86pc-ucs2 py2.4-solaris-2.10-sun4u-ucs2
-py2.5-solaris = py2.5-solaris-2.11-i86pc-ucs2 py2.5-solaris-2.10-sun4u-ucs2
-py2.6-solaris = py2.6-solaris-2.11-i86pc-ucs2 py2.6-solaris-2.10-sun4u-ucs2
+py2.4-solaris = py2.4-solaris-2.10-i86pc-ucs2 py2.4-solaris-2.11-i86pc-ucs2 py2.4-solaris-2.10-sun4u-ucs2
+py2.5-solaris = py2.5-solaris-2.10-i86pc-ucs2 py2.5-solaris-2.11-i86pc-ucs2 py2.5-solaris-2.10-sun4u-ucs2
+py2.6-solaris = py2.6-solaris-2.10-i86pc-ucs2 py2.6-solaris-2.11-i86pc-ucs2 py2.6-solaris-2.10-sun4u-ucs2
solaris = py2.4-solaris py2.5-solaris py2.6-solaris
py2.4-all = py2.4-linux py2.4-macosx py2.4-solaris
py2.5-all = py2.5-linux py2.5-macosx py2.5-solaris
diff --git a/eggs.ini b/eggs.ini
index 016d7603c0d..556e67bdd20 100644
--- a/eggs.ini
+++ b/eggs.ini
@@ -19,7 +19,7 @@ MySQL_python = 1.2.2
pbs_python = 2.9.4
psycopg2 = 2.0.6
pycrypto = 2.0.1
-pysqlite = 2.3.5
+pysqlite = 2.5.6
python_lzo = 1.08
threadframe = 0.2
guppy = 0.1.8
@@ -57,11 +57,12 @@ boto = 1.8d
; extra version information
[tags]
psycopg2 = _8.2.6_static
-pysqlite = _3.5.4_static
+pysqlite = _static
MySQL_python = _5.0.67_static
python_lzo = _static
bx_python = _dev_r4bf1f32e6b76
-GeneTrack = _dev_raa786e9fc131d998e532a1aef39d108850c9e93d
+GeneTrack = _dev_e380f21c704218622155b9d230a44b3c9c452524
+SQLAlchemy = _dev_r6498
; nose = .dev_r7156749efc58
; source location, necessary for scrambling
@@ -73,7 +74,7 @@ MySQL_python = http://superb-west.dl.sourceforge.net/sourceforge/mysql-python/My
pbs_python = http://ftp.sara.nl/pub/outgoing/pbs_python-2.9.4.tar.gz
psycopg2 = http://initd.org/pub/software/psycopg/PSYCOPG-2-0/psycopg2-2.0.6.tar.gz ftp://ftp-archives.postgresql.org/pub/source/v8.2.6/postgresql-8.2.6.tar.bz2
pycrypto = http://www.amk.ca/files/python/crypto/pycrypto-2.0.1.tar.gz
-pysqlite = http://initd.org/pub/software/pysqlite/releases/2.3/2.3.5/pysqlite-2.3.5.tar.gz http://www.sqlite.org/sqlite-source-3_5_4.zip
+pysqlite = http://pypi.python.org/packages/source/p/pysqlite/pysqlite-2.5.6.tar.gz
python_lzo = http://www.oberhumer.com/opensource/lzo/download/LZO-v1/python-lzo-1.08.tar.gz http://www.oberhumer.com/opensource/lzo/download/LZO-v1/lzo-1.08.tar.gz
threadframe = http://www.majid.info/python/threadframe/threadframe-0.2.tar.gz
guppy = http://pypi.python.org/packages/source/g/guppy/guppy-0.1.8.tar.gz
@@ -82,7 +83,7 @@ Beaker = http://cheeseshop.python.org/packages/source/B/Beaker/Beaker-1.4.tar.gz
decorator = http://pypi.python.org/packages/source/d/decorator/decorator-3.1.2.tar.gz
docutils = http://downloads.sourceforge.net/docutils/docutils-0.4.tar.gz
elementtree = http://effbot.org/downloads/elementtree-1.2.6-20050316.tar.gz
-GeneTrack = http://github.com/ialbert/genetrack-central/tarball/aa786e9fc131d998e532a1aef39d108850c9e93d
+GeneTrack = http://github.com/ialbert/genetrack-central/tarball/e380f21c704218622155b9d230a44b3c9c452524
lrucache = http://evan.prodromou.name/lrucache/lrucache-0.2.tar.gz
Mako = http://www.makotemplates.org/downloads/Mako-0.2.5.tar.gz
nose = http://pypi.python.org/packages/source/n/nose/nose-0.11.1.tar.gz
@@ -93,7 +94,7 @@ PasteScript = http://cheeseshop.python.org/packages/source/P/PasteScript/PasteSc
PSI = http://pypi.python.org/packages/source/P/PSI/PSI-0.3b1.1.tar.gz
Routes = http://pypi.python.org/packages/source/R/Routes/Routes-1.11.tar.gz
simplejson = http://cheeseshop.python.org/packages/source/s/simplejson/simplejson-1.5.tar.gz
-SQLAlchemy = http://pypi.python.org/packages/source/S/SQLAlchemy/SQLAlchemy-0.5.6.tar.gz
+SQLAlchemy = http://dist.g2.bx.psu.edu/SQLAlchemy-0.5.6_r6498.tar.bz2
sqlalchemy_migrate = http://pypi.python.org/packages/source/s/sqlalchemy-migrate/sqlalchemy-migrate-0.5.4.tar.gz
Tempita = http://pypi.python.org/packages/source/T/Tempita/Tempita-0.1.tar.gz
twill = http://darcs.idyll.org/~t/projects/twill-0.9.tar.gz
diff --git a/lib/galaxy/datatypes/binary.py b/lib/galaxy/datatypes/binary.py
new file mode 100644
index 00000000000..7a61bc4222b
--- /dev/null
+++ b/lib/galaxy/datatypes/binary.py
@@ -0,0 +1,156 @@
+"""
+Binary classes
+"""
+
+import data, logging, binascii
+from galaxy.datatypes.metadata import MetadataElement
+from galaxy.datatypes import metadata
+from galaxy.datatypes.sniff import *
+from urllib import urlencode, quote_plus
+import zipfile
+import os, subprocess, tempfile
+
+log = logging.getLogger(__name__)
+
+sniffable_binary_formats = [ 'sff' ]
+# Currently these supported binary data types must be manually set on upload
+unsniffable_binary_formats = [ 'ab1', 'scf' ]
+
+class Binary( data.Data ):
+ """Binary data"""
+ def set_peek( self, dataset ):
+ """Set the peek and blurb text"""
+ if not dataset.dataset.purged:
+ dataset.peek = 'binary data'
+ dataset.blurb = 'data'
+ else:
+ dataset.peek = 'file does not exist'
+ dataset.blurb = 'file purged from disk'
+
+class Ab1( Binary ):
+ """Class describing an ab1 binary sequence file"""
+ file_ext = "ab1"
+ def set_peek( self, dataset ):
+ if not dataset.dataset.purged:
+ export_url = "/history_add_to?" + urlencode( {'history_id':dataset.history_id,'ext':'ab1','name':'ab1 sequence','info':'Sequence file','dbkey':dataset.dbkey} )
+ dataset.peek = "Binary ab1 sequence file"
+ dataset.blurb = data.nice_size( dataset.get_size() )
+ else:
+ dataset.peek = 'file does not exist'
+ dataset.blurb = 'file purged from disk'
+ def display_peek( self, dataset ):
+ try:
+ return dataset.peek
+ except:
+ return "Binary ab1 sequence file (%s)" % ( data.nice_size( dataset.get_size() ) )
+
+class Bam( Binary ):
+ """Class describing a BAM binary file"""
+ file_ext = "bam"
+ MetadataElement( name="bam_index", desc="BAM Index File", param=metadata.FileParameter, readonly=True, no_value=None, visible=False, optional=True )
+ def init_meta( self, dataset, copy_from=None ):
+ Binary.init_meta( self, dataset, copy_from=copy_from )
+ def set_meta( self, dataset, overwrite = True, **kwd ):
+ """
+ Sets index for BAM file.
+ """
+ index_file = dataset.metadata.bam_index
+ if not index_file:
+ index_file = dataset.metadata.spec['bam_index'].param.new_file( dataset = dataset )
+ tmp_dir = tempfile.gettempdir()
+ tmpf1 = tempfile.NamedTemporaryFile( dir=tmp_dir )
+ tmpf1bai = '%s.bai' % tmpf1.name
+ try:
+ os.system( 'cd %s' % tmp_dir )
+ os.system( 'cp %s %s' % ( dataset.file_name, tmpf1.name ) )
+ os.system( 'samtools index %s' % tmpf1.name )
+ os.system( 'cp %s %s' % ( tmpf1bai, index_file.file_name ) )
+ except Exception, ex:
+ sys.stderr.write( 'There was a problem creating the index for the BAM file\n%s\n' + str( ex ) )
+ tmpf1.close()
+ if os.path.exists( tmpf1bai ):
+ os.remove( tmpf1bai )
+ dataset.metadata.bam_index = index_file
+ def set_peek( self, dataset ):
+ if not dataset.dataset.purged:
+ export_url = "/history_add_to?" + urlencode( {'history_id':dataset.history_id,'ext':'bam','name':'bam alignments','info':'Alignments file','dbkey':dataset.dbkey} )
+ dataset.peek = "Binary bam alignments file"
+ dataset.blurb = data.nice_size( dataset.get_size() )
+ else:
+ dataset.peek = 'file does not exist'
+ dataset.blurb = 'file purged from disk'
+ def display_peek( self, dataset ):
+ try:
+ return dataset.peek
+ except:
+ return "Binary bam alignments file (%s)" % ( data.nice_size( dataset.get_size() ) )
+ def get_mime( self ):
+ """Returns the mime type of the datatype"""
+ return 'application/octet-stream'
+
+class Binseq( Binary ):
+ """Class describing a zip archive of binary sequence files"""
+ file_ext = "binseq.zip"
+ def set_peek( self, dataset ):
+ if not dataset.dataset.purged:
+ zip_file = zipfile.ZipFile( dataset.file_name, "r" )
+ num_files = len( zip_file.namelist() )
+ dataset.peek = "Archive of %s binary sequence files" % ( str( num_files ) )
+ dataset.blurb = data.nice_size( dataset.get_size() )
+ else:
+ dataset.peek = 'file does not exist'
+ dataset.blurb = 'file purged from disk'
+ def display_peek( self, dataset ):
+ try:
+ return dataset.peek
+ except:
+ return "Binary sequence file archive (%s)" % ( data.nice_size( dataset.get_size() ) )
+ def get_mime( self ):
+ """Returns the mime type of the datatype"""
+ return 'application/zip'
+
+class Scf( Binary ):
+ """Class describing an scf binary sequence file"""
+ file_ext = "scf"
+ def set_peek( self, dataset ):
+ if not dataset.dataset.purged:
+ export_url = "/history_add_to?" + urlencode({'history_id':dataset.history_id,'ext':'scf','name':'scf sequence','info':'Sequence file','dbkey':dataset.dbkey})
+ dataset.peek = "Binary scf sequence file"
+ dataset.blurb = data.nice_size( dataset.get_size() )
+ else:
+ dataset.peek = 'file does not exist'
+ dataset.blurb = 'file purged from disk'
+ def display_peek( self, dataset ):
+ try:
+ return dataset.peek
+ except:
+ return "Binary scf sequence file (%s)" % ( data.nice_size( dataset.get_size() ) )
+
+class Sff( Binary ):
+ """ Standard Flowgram Format (SFF) """
+ file_ext = "sff"
+ def __init__( self, **kwd ):
+ Binary.__init__( self, **kwd )
+ def sniff( self, filename ):
+ # The first 4 bytes of any sff file is '.sff', and the file is binary. For details
+ # about the format, see http://www.ncbi.nlm.nih.gov/Traces/trace.cgi?cmd=show&f=formats&m=doc&s=format
+ try:
+ header = open( filename ).read(4)
+ if binascii.b2a_hex( header ) == binascii.hexlify( '.sff' ):
+ return True
+ return False
+ except Exception, e:
+ return False
+ def set_peek( self, dataset ):
+ if not dataset.dataset.purged:
+ export_url = "/history_add_to?" + urlencode( {'history_id':dataset.history_id,'ext':'sff','name':'sff file','info':'sff file','dbkey':dataset.dbkey} )
+ dataset.peek = "Binary sff file"
+ dataset.blurb = data.nice_size( dataset.get_size() )
+ else:
+ dataset.peek = 'file does not exist'
+ dataset.blurb = 'file purged from disk'
+ def display_peek( self, dataset ):
+ try:
+ return dataset.peek
+ except:
+ return "Binary sff file (%s)" % ( data.nice_size( dataset.get_size() ) )
diff --git a/lib/galaxy/datatypes/data.py b/lib/galaxy/datatypes/data.py
index 539aded117b..531799fbb0e 100644
--- a/lib/galaxy/datatypes/data.py
+++ b/lib/galaxy/datatypes/data.py
@@ -1,4 +1,4 @@
-import logging, os, sys, time, tempfile, binascii
+import logging, os, sys, time, tempfile
from galaxy import util
from galaxy.util.odict import odict
from galaxy.util.bunch import Bunch
@@ -40,20 +40,18 @@ class Data( object ):
"""
__metaclass__ = DataMeta
-
- """Add metadata elements"""
+ # Add metadata elements
MetadataElement( name="dbkey", desc="Database/Build", default="?", param=metadata.DBKeyParameter, multiple=False, no_value="?" )
-
- """Stores the set of display applications, and viewing methods, supported by this datatype """
+ # Stores the set of display applications, and viewing methods, supported by this datatype
supported_display_apps = {}
-
- """If False, the peek is regenerated whenever a dataset of this type is copied"""
+ # If False, the peek is regenerated whenever a dataset of this type is copied
copy_safe_peek = True
-
- is_binary = True #The dataset contains binary data --> do not space_to_tab or convert newlines, etc. Allow binary file uploads of this type when True.
-
- allow_datatype_change = True #Allow user to change between this datatype and others. If False, this datatype cannot be changed from or into.
-
+ # The dataset contains binary data --> do not space_to_tab or convert newlines, etc.
+ # Allow binary file uploads of this type when True.
+ is_binary = True
+ # Allow user to change between this datatype and others. If False, this datatype
+ # cannot be changed from or into.
+ allow_datatype_change = True
#Composite datatypes
composite_type = None
composite_files = odict()
@@ -162,6 +160,11 @@ class Data( object ):
info = info.replace( '\r', ' ' )
if info.find( '\n' ) >= 0:
info = info.replace( '\n', ' ' )
+
+ # Convert to unicode to display non-ascii characters.
+ if type( info ) is not unicode:
+ info = unicode( info, 'utf-8')
+
return info
except:
return "info unavailable"
@@ -270,8 +273,6 @@ class Data( object ):
def add_composite_file( self, name, **kwds ):
#self.composite_files = self.composite_files.copy()
self.composite_files[ name ] = self.__new_composite_file( name, **kwds )
-
-
def __substitute_composite_key( self, key, composite_file, dataset = None ):
if composite_file.substitute_name_with_metadata:
if dataset:
@@ -303,7 +304,6 @@ class Data( object ):
return files
def generate_auto_primary_file( self, dataset = None ):
raise Exception( "generate_auto_primary_file is not implemented for this datatype." )
-
@property
def has_resolution(self):
return False
@@ -364,23 +364,37 @@ class Text( Data ):
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
-class Binary( Data ):
- """Binary data"""
+class Txtseq( Data ):
+ """Class describing a zip archive of text sequence files"""
+ file_ext = "txtseq.zip"
def set_peek( self, dataset ):
- """Set the peek and blurb text"""
if not dataset.dataset.purged:
- dataset.peek = 'binary data'
- dataset.blurb = 'data'
+ zip_file = zipfile.ZipFile( dataset.file_name, "r" )
+ num_files = len( zip_file.namelist() )
+ dataset.peek = "Archive of %s text sequence files" % ( str( num_files ) )
+ dataset.blurb = data.nice_size( dataset.get_size() )
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+ def display_peek(self, dataset):
+ try:
+ return dataset.peek
+ except:
+ return "Text sequence file archive (%s)" % ( data.nice_size( dataset.get_size() ) )
+ def get_mime(self):
+ """Returns the mime type of the datatype"""
+ return 'application/zip'
+
+class Newick( Text ):
+ pass
+
+# ------------- Utility methods --------------
def get_test_fname( fname ):
"""Returns test data filename"""
path, name = os.path.split(__file__)
full_path = os.path.join( path, 'test', fname )
return full_path
-
def nice_size(size):
"""
Returns a readably formatted string with the size
@@ -406,7 +420,6 @@ def nice_size(size):
out = "%.1f %s" % (size, word)
return out
return '??? bytes'
-
def get_file_peek( file_name, is_multi_byte=False, WIDTH=256, LINE_COUNT=5 ):
"""
Returns the first LINE_COUNT lines wrapped to WIDTH
@@ -443,7 +456,6 @@ def get_file_peek( file_name, is_multi_byte=False, WIDTH=256, LINE_COUNT=5 ):
else:
text = unicode( '\n'.join( lines ), 'utf-8' )
return text
-
def get_line_count(file_name):
"""Returns the number of lines in a file that are neither null nor comments"""
count = 0
@@ -452,38 +464,3 @@ def get_line_count(file_name):
if line and line[0] != '#':
count += 1
return count
-
-class Newick( Text ):
- pass
-
-class Sff( Binary ):
- """ Standard Flowgram Format (SFF) """
- file_ext = "sff"
- def __init__( self, **kwd ):
- Binary.__init__(self, **kwd)
- def init_meta( self, dataset, copy_from=None ):
- Binary.init_meta( self, dataset, copy_from=copy_from )
- def sniff( self, filename ):
- '''
- The first 4 bytes of any sff file is '.sff'
-
- >>> fname = get_test_fname( '1.sff' )
- >>> Sff().sniff( fname )
- True
- '''
- header = open( filename ).read(4)
- if binascii.b2a_hex( header ) == binascii.hexlify( '.sff' ):
- return True
- return False
- def set_peek( self, dataset ):
- if not dataset.dataset.purged:
- dataset.peek = "Binary sff file"
- dataset.blurb = nice_size( dataset.get_size() )
- else:
- dataset.peek = 'file does not exist'
- dataset.blurb = 'file purged from disk'
- def display_peek(self, dataset):
- try:
- return dataset.peek
- except:
- return "sff file (%s)" % ( nice_size( dataset.get_size() ) )
diff --git a/lib/galaxy/datatypes/genetics.py b/lib/galaxy/datatypes/genetics.py
index 0e0b739f9eb..565fcddbbc7 100644
--- a/lib/galaxy/datatypes/genetics.py
+++ b/lib/galaxy/datatypes/genetics.py
@@ -1,6 +1,5 @@
"""
rgenetics datatypes
-Use at your peril
Ross Lazarus
for the rgenetics and galaxy projects
@@ -11,7 +10,6 @@ subsequent row values are all numeric ! Will fail if any non numeric (eg '+' or
ross lazarus for rgenetics
august 20 2007
"""
-
import logging, os, sys, time, tempfile, shutil, string, glob
import data
from galaxy import util
@@ -26,8 +24,7 @@ from galaxy.datatypes.images import Html
from galaxy.datatypes.interval import Interval
from galaxy.util.hash_util import *
-gal_Log = logging.getLogger(__name__)
-verbose = False
+log = logging.getLogger(__name__)
class GenomeGraphs(Interval):
@@ -48,10 +45,8 @@ class GenomeGraphs(Interval):
"""Initialize datatype, by adding GBrowse display app"""
Interval.__init__(self, **kwd)
self.add_display_app ( 'ucsc', 'display at UCSC', 'as_ucsc_display_file', 'ucsc_links' )
-
def as_ucsc_display_file( self, dataset, **kwd ):
return open( dataset.file_name )
-
def set_meta( self, dataset, overwrite = True, **kwd ):
i = 0
for i, line in enumerate( file ( dataset.file_name ) ):
@@ -66,7 +61,6 @@ class GenomeGraphs(Interval):
except:
pass
Interval.set_meta( self, dataset, overwrite = overwrite, skip = i )
-
def make_html_table( self, dataset, skipchars=[] ):
"""Create HTML table, used for displaying peek"""
out = ['
']
@@ -82,7 +76,6 @@ class GenomeGraphs(Interval):
except Exception, exc:
out = "Can't create peek %s" % exc
return out
-
def get_estimated_display_viewport( self, dataset ):
"""
Return a chrom, start, stop tuple for viewing a file. There are slight differences between gff 2 and gff 3
@@ -118,7 +111,6 @@ class GenomeGraphs(Interval):
return ( seqid, str( start ), str( stop ) )
else:
return ( '', '', '' )
-
def gbrowse_links( self, dataset, type, app, base_url ):
ret_val = []
if dataset.has_data:
@@ -132,7 +124,6 @@ class GenomeGraphs(Interval):
link = "%s?start=%s&stop=%s&ref=%s&dbkey=%s" % ( site_url, start, stop, seqid, dataset.dbkey )
ret_val.append( ( site_name, link ) )
return ret_val
-
def ucsc_links( self, dataset, type, app, base_url ):
ret_val = []
if dataset.has_data:
@@ -160,10 +151,8 @@ class GenomeGraphs(Interval):
link = '%s?redirect_url=%s&display_url=%s' % ( internal_url, redirect_url, display_url )
ret_val.append( (site_name, link) )
else:
- gal_Log.debug('@@@ gg ucsc_links - no viewport_tuple')
+ log.debug('@@@ gg ucsc_links - no viewport_tuple')
return ret_val
-
-
def sniff( self, filename ):
"""
Determines whether the file is in gff format
@@ -202,20 +191,17 @@ class GenomeGraphs(Interval):
except:
return False
-
-
class rgTabList(Tabular):
- """ for sampleid and for featureid lists of exclusions or inclusions in the clean tool
+ """
+ for sampleid and for featureid lists of exclusions or inclusions in the clean tool
featureid subsets on statistical criteria -> specialized display such as gg
"""
file_ext = "rgTList"
-
def __init__(self, **kwd):
"""Initialize featurelistt datatype"""
Tabular.__init__( self, **kwd )
self.column_names = []
-
def make_html_table( self, dataset, skipchars=[] ):
"""Create HTML table, used for displaying peek"""
out = ['
']
@@ -236,23 +222,24 @@ class rgTabList(Tabular):
out = "Can't create peek %s" % exc
return out
-
class rgSampleList(rgTabList):
- """ for sampleid exclusions or inclusions in the clean tool
- output from QC eg excess het, gender error, ibd pair member,eigen outlier,excess mendel errors,...
- since they can be uploaded, should be flexible
- but they are persistent at least
- same infrastructure for expression?
+ """
+ for sampleid exclusions or inclusions in the clean tool
+ output from QC eg excess het, gender error, ibd pair member,eigen outlier,excess mendel errors,...
+ since they can be uploaded, should be flexible
+ but they are persistent at least
+ same infrastructure for expression?
"""
file_ext = "rgSList"
def __init__(self, **kwd):
- """Initialize samplelist datatype"""
+ """
+ Initialize samplelist datatype
+ """
rgTabList.__init__( self, **kwd )
self.column_names[0] = 'FID'
self.column_names[1] = 'IID'
# this is what Plink wants as at 2009
-
def sniff(self,filename):
"""
"""
@@ -264,10 +251,11 @@ class rgSampleList(rgTabList):
return False
class rgFeatureList( rgTabList ):
- """ for featureid lists of exclusions or inclusions in the clean tool
- output from QC eg low maf, high missingness, bad hwe in controls, excess mendel errors,...
- featureid subsets on statistical criteria -> specialized display such as gg
- same infrastructure for expression?
+ """
+ for featureid lists of exclusions or inclusions in the clean tool
+ output from QC eg low maf, high missingness, bad hwe in controls, excess mendel errors,...
+ featureid subsets on statistical criteria -> specialized display such as gg
+ same infrastructure for expression?
"""
file_ext = "rgFList"
@@ -276,26 +264,23 @@ class rgFeatureList( rgTabList ):
rgTabList.__init__( self, **kwd )
for i,s in enumerate(['#FeatureId', 'Chr', 'Genpos', 'Mappos']):
self.column_names[i] = s
-
class Rgenetics(Html):
- """class to use for rgenetics"""
-
- MetadataElement( name="base_name", desc="base name for all transformed versions of this genetic dataset", default="rgenetics",
- readonly=True, set_in_upload=True)
+ """
+ class to use for rgenetics
+ """
+ MetadataElement( name="base_name", desc="base name for all transformed versions of this genetic dataset", default="rgenetics", readonly=True, set_in_upload=True)
composite_type = 'auto_primary_file'
allow_datatype_change = False
file_ext = 'rgenetics'
-
def missing_meta( self, dataset=None, **kwargs):
"""Checks for empty meta values"""
for key, value in dataset.metadata.items():
if not value:
return True
return False
-
def generate_primary_file( self, dataset = None ):
rval = ['Rgenetics Galaxy Composite Dataset ']
rval.append('
This composite dataset is composed of the following files:
')
@@ -306,9 +291,9 @@ class Rgenetics(Html):
rval.append( '
' )
return "\n".join( rval )
-
def regenerate_primary_file(self,dataset):
- """cannot do this until we are setting metadata
+ """
+ cannot do this until we are setting metadata
"""
def fix(oldpath,newbase):
old,e = os.path.splitext(oldpath)
@@ -332,30 +317,25 @@ class Rgenetics(Html):
f.write("\n".join( rval ))
f.write('\n')
f.close()
-
def set_meta( self, dataset, **kwd ):
-
- """for lped/pbed eg
-
+ """
+ for lped/pbed eg
"""
if kwd.get('overwrite') == False:
- if verbose:
- gal_Log.debug('@@@ rgenetics set_meta called with overwrite = False')
+ #log.debug('@@@ rgenetics set_meta called with overwrite = False')
return True
try:
efp = dataset.extra_files_path
except:
- if verbose:
- gal_Log.debug('@@@rgenetics set_meta failed %s - dataset %s has no efp ?' % (sys.exc_info()[0], dataset.name))
+ #log.debug('@@@rgenetics set_meta failed %s - dataset %s has no efp ?' % (sys.exc_info()[0], dataset.name))
return False
try:
- flist = os.listdir(efp)
- except:
- if verbose: gal_Log.debug('@@@rgenetics set_meta failed %s - dataset %s has no efp ?' % (sys.exc_info()[0],dataset.name))
+ flist = os.listdir(efp)
+ except:
+ #log.debug('@@@rgenetics set_meta failed %s - dataset %s has no efp ?' % (sys.exc_info()[0],dataset.name))
return False
if len(flist) == 0:
- if verbose:
- gal_Log.debug('@@@rgenetics set_meta failed - %s efp %s is empty?' % (dataset.name,efp))
+ #log.debug('@@@rgenetics set_meta failed - %s efp %s is empty?' % (dataset.name,efp))
return False
bn = None
for f in flist:
@@ -372,9 +352,9 @@ class Rgenetics(Html):
dataset.blurb = 'Composite file - Rgenetics Galaxy toolkit'
return True
-
class SNPMatrix(Rgenetics):
- """fake class to distinguish different species of Rgenetics data collections
+ """
+ fake class to distinguish different species of Rgenetics data collections
"""
file_ext="snpmatrix"
@@ -385,9 +365,9 @@ class SNPMatrix(Rgenetics):
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
-
def sniff(self,filename):
- """ need to check the file header hex code
+ """
+ need to check the file header hex code
"""
infile = open(dataset.file_name, "b")
head = infile.read(16)
@@ -397,9 +377,9 @@ class SNPMatrix(Rgenetics):
else:
return True
-
class Lped(Rgenetics):
- """fake class to distinguish different species of Rgenetics data collections
+ """
+ fake class to distinguish different species of Rgenetics data collections
"""
file_ext="lped"
@@ -408,9 +388,9 @@ class Lped(Rgenetics):
self.add_composite_file( '%s.ped', description = 'Pedigree File', substitute_name_with_metadata = 'base_name', is_binary = True )
self.add_composite_file( '%s.map', description = 'Map File', substitute_name_with_metadata = 'base_name', is_binary = True )
-
class Pphe(Rgenetics):
- """fake class to distinguish different species of Rgenetics data collections
+ """
+ fake class to distinguish different species of Rgenetics data collections
"""
file_ext="pphe"
@@ -418,14 +398,15 @@ class Pphe(Rgenetics):
Rgenetics.__init__(self, **kwd)
self.add_composite_file( '%s.pphe', description = 'Plink Phenotype File', substitute_name_with_metadata = 'base_name' )
-
class Lmap(Rgenetics):
- """fake class to distinguish different species of Rgenetics data collections
+ """
+ fake class to distinguish different species of Rgenetics data collections
"""
file_ext="lmap"
class Fphe(Rgenetics):
- """fake class to distinguish different species of Rgenetics data collections
+ """
+ fake class to distinguish different species of Rgenetics data collections
"""
file_ext="fphe"
@@ -434,7 +415,8 @@ class Fphe(Rgenetics):
self.add_composite_file( '%s.fphe', description = 'FBAT Phenotype File', substitute_name_with_metadata = 'base_name' )
class Phe(Rgenetics):
- """fake class to distinguish different species of Rgenetics data collections
+ """
+ fake class to distinguish different species of Rgenetics data collections
"""
file_ext="phe"
@@ -442,10 +424,9 @@ class Phe(Rgenetics):
Rgenetics.__init__(self, **kwd)
self.add_composite_file( '%s.phe', description = 'Phenotype File', substitute_name_with_metadata = 'base_name' )
-
-
class Fped(Rgenetics):
- """fake class to distinguish different species of Rgenetics data collections
+ """
+ fake class to distinguish different species of Rgenetics data collections
"""
file_ext="fped"
@@ -453,9 +434,9 @@ class Fped(Rgenetics):
Rgenetics.__init__(self, **kwd)
self.add_composite_file( '%s.fped', description = 'FBAT format pedfile', substitute_name_with_metadata = 'base_name' )
-
class Pbed(Rgenetics):
- """fake class to distinguish different species of Rgenetics data collections
+ """
+ fake class to distinguish different species of Rgenetics data collections
"""
file_ext="pbed"
@@ -466,7 +447,8 @@ class Pbed(Rgenetics):
self.add_composite_file( '%s.fam', substitute_name_with_metadata = 'base_name', is_binary = True )
class Eigenstratgeno(Rgenetics):
- """fake class to distinguish different species of Rgenetics data collections
+ """
+ fake class to distinguish different species of Rgenetics data collections
"""
file_ext="eigenstratgeno"
@@ -475,11 +457,10 @@ class Eigenstratgeno(Rgenetics):
self.add_composite_file( '%s.eigenstratgeno', substitute_name_with_metadata = 'base_name', is_binary = True )
self.add_composite_file( '%s.ind', substitute_name_with_metadata = 'base_name', is_binary = True )
self.add_composite_file( '%s.map', substitute_name_with_metadata = 'base_name', is_binary = True )
-
-
class Eigenstratpca(Rgenetics):
- """fake class to distinguish different species of Rgenetics data collections
+ """
+ fake class to distinguish different species of Rgenetics data collections
"""
file_ext="eigenstratpca"
@@ -487,22 +468,21 @@ class Eigenstratpca(Rgenetics):
Rgenetics.__init__(self, **kwd)
self.add_composite_file( '%s.eigenstratpca', description = 'Eigenstrat PCA file', substitute_name_with_metadata = 'base_name' )
-
class Snptest(Rgenetics):
- """fake class to distinguish different species of Rgenetics data collections
+ """
+ fake class to distinguish different species of Rgenetics data collections
"""
file_ext="snptest"
-
class Pheno(Tabular):
"""
base class for pheno files
"""
file_ext = 'pheno'
-
class RexpBase( Html ):
- """base class for BioC data structures in Galaxy
+ """
+ base class for BioC data structures in Galaxy
must be constructed with the pheno data in place since that
goes into the metadata for each instance
"""
@@ -518,18 +498,16 @@ class RexpBase( Html ):
composite_type = 'auto_primary_file'
allow_datatype_change = False
-
def __init__( self, **kwd ):
Html.__init__(self,**kwd)
self.add_composite_file( '%s.pheno', description = 'Phenodata tab text file',
substitute_name_with_metadata = 'base_name', is_binary=True)
-
def generate_primary_file( self, dataset = None ):
- """ This is called only at upload to write the html file
+ """
+ This is called only at upload to write the html file
cannot rename the datasets here - they come with the default unfortunately
"""
return 'AutoGenerated Primary File for Composite Dataset'
-
def get_phecols(self, phenolist=[], maxConc=20):
"""
sept 2009: cannot use whitespace to split - make a more complex structure here
@@ -555,7 +533,7 @@ class RexpBase( Html ):
else:
for col,code in enumerate(row): # keep column order correct
if col >= totcols:
- gal_Log.warning('### get_phecols error in pheno file - row %d col %d (%s) longer than header %s' % (nrows, col, row, head))
+ log.warning('### get_phecols error in pheno file - row %d col %d (%s) longer than header %s' % (nrows, col, row, head))
else:
concordance[col].setdefault(code,0) # first one is zero
concordance[col][code] += 1
@@ -601,10 +579,9 @@ class RexpBase( Html ):
res = [('no usable phenotype columns found',[('?',0),]),]
return res
-
-
def get_pheno(self,dataset):
- """expects a .pheno file in the extra_files_dir - ugh
+ """
+ expects a .pheno file in the extra_files_dir - ugh
note that R is wierd and adds the row.name in
the header so the columns are all wrong - unless you tell it not to.
A file can be written as
@@ -620,11 +597,12 @@ class RexpBase( Html ):
else:
p = []
return '\n'.join(p)
-
def set_peek( self, dataset ):
- """expects a .pheno file in the extra_files_dir - ugh
+ """
+ expects a .pheno file in the extra_files_dir - ugh
note that R is wierd and does not include the row.name in
- the header. why?"""
+ the header. why?
+ """
if not dataset.dataset.purged:
pp = os.path.join(dataset.extra_files_path,'%s.pheno' % dataset.metadata.base_name)
try:
@@ -636,17 +614,14 @@ class RexpBase( Html ):
else:
dataset.peek = 'file does not exist\n'
dataset.blurb = 'file purged from disk'
-
def get_peek( self, dataset ):
- """expects a .pheno file in the extra_files_dir - ugh
- """
+ """expects a .pheno file in the extra_files_dir - ugh"""
pp = os.path.join(dataset.extra_files_path,'%s.pheno' % dataset.metadata.base_name)
try:
p = file(pp,'r').readlines()
except:
p = ['##failed to find %s' % pp]
return ''.join(p[:5])
-
def get_file_peek(self,filename):
"""
can't really peek at a filename - need the extra_files_path and such?
@@ -657,7 +632,6 @@ class RexpBase( Html ):
except:
pass
return ''.join(h[:5])
-
def regenerate_primary_file(self,dataset):
"""cannot do this until we are setting metadata
"""
@@ -672,24 +646,19 @@ class RexpBase( Html ):
f.write("\n".join( rval ))
f.write('\n')
f.close()
-
- """Add metadata elements"""
def init_meta( self, dataset, copy_from=None ):
+ """Add metadata elements"""
if copy_from:
dataset.metadata = copy_from.metadata
-
def set_meta( self, dataset, **kwd ):
-
"""
NOTE we apply the tabular machinary to the phenodata extracted
from a BioC eSet or affybatch.
-
"""
try:
flist = os.listdir(dataset.extra_files_path)
except:
- if verbose:
- gal_Log.debug('@@@rexpression set_meta failed - no dataset?')
+ #log.debug('@@@rexpression set_meta failed - no dataset?')
return False
bn = None
for f in flist:
@@ -727,7 +696,6 @@ class RexpBase( Html ):
if not dataset.blurb:
dataset.blurb = 'R loadable BioC expression object for the Rexpression Galaxy toolkit'
return True
-
def make_html_table( self, pp='nothing supplied from peek\n'):
"""Create HTML table, used for displaying peek"""
out = ['
',]
@@ -750,20 +718,16 @@ class RexpBase( Html ):
except Exception, exc:
out = "Can't create html table %s" % str( exc )
return out
-
def display_peek( self, dataset ):
"""Returns formatted html of peek"""
out=self.make_html_table(dataset.peek)
return out
-
def get_mime(self):
"""Returns the mime type of the datatype"""
return 'text/html'
-
class Affybatch( RexpBase ):
"""derived class for BioC data structures in Galaxy """
-
file_ext = "affybatch"
def __init__( self, **kwd ):
@@ -780,7 +744,6 @@ class Eset( RexpBase ):
self.add_composite_file( '%s.eset', description = 'ESet R object saved to file',
substitute_name_with_metadata = 'base_name', is_binary = True )
-
class MAlist( RexpBase ):
"""derived class for BioC data structures in Galaxy """
file_ext = "malist"
@@ -790,9 +753,6 @@ class MAlist( RexpBase ):
self.add_composite_file( '%s.malist', description = 'MAlist R object saved to file',
substitute_name_with_metadata = 'base_name', is_binary = True )
-
if __name__ == '__main__':
import doctest, sys
doctest.testmod(sys.modules[__name__])
-
-
diff --git a/lib/galaxy/datatypes/images.py b/lib/galaxy/datatypes/images.py
index 17d0f659a8d..a5e17965446 100644
--- a/lib/galaxy/datatypes/images.py
+++ b/lib/galaxy/datatypes/images.py
@@ -13,82 +13,6 @@ import os, subprocess, tempfile
log = logging.getLogger(__name__)
-class Ab1( data.Data ):
- """Class describing an ab1 binary sequence file"""
- file_ext = "ab1"
- def set_peek( self, dataset ):
- if not dataset.dataset.purged:
- export_url = "/history_add_to?" + urlencode({'history_id':dataset.history_id,'ext':'ab1','name':'ab1 sequence','info':'Sequence file','dbkey':dataset.dbkey})
- dataset.peek = "Binary ab1 sequence file"
- dataset.blurb = data.nice_size( dataset.get_size() )
- else:
- dataset.peek = 'file does not exist'
- dataset.blurb = 'file purged from disk'
- def display_peek(self, dataset):
- try:
- return dataset.peek
- except:
- return "Binary ab1 sequence file (%s)" % ( data.nice_size( dataset.get_size() ) )
-
-class Scf( data.Data ):
- """Class describing an scf binary sequence file"""
- file_ext = "scf"
- def set_peek( self, dataset ):
- if not dataset.dataset.purged:
- export_url = "/history_add_to?" + urlencode({'history_id':dataset.history_id,'ext':'scf','name':'scf sequence','info':'Sequence file','dbkey':dataset.dbkey})
- dataset.peek = "Binary scf sequence file"
- dataset.blurb = data.nice_size( dataset.get_size() )
- else:
- dataset.peek = 'file does not exist'
- dataset.blurb = 'file purged from disk'
- def display_peek(self, dataset):
- try:
- return dataset.peek
- except:
- return "Binary scf sequence file (%s)" % ( data.nice_size( dataset.get_size() ) )
-
-class Binseq( data.Data ):
- """Class describing a zip archive of binary sequence files"""
- file_ext = "binseq.zip"
- def set_peek( self, dataset ):
- if not dataset.dataset.purged:
- zip_file = zipfile.ZipFile( dataset.file_name, "r" )
- num_files = len( zip_file.namelist() )
- dataset.peek = "Archive of %s binary sequence files" % ( str( num_files ) )
- dataset.blurb = data.nice_size( dataset.get_size() )
- else:
- dataset.peek = 'file does not exist'
- dataset.blurb = 'file purged from disk'
- def display_peek(self, dataset):
- try:
- return dataset.peek
- except:
- return "Binary sequence file archive (%s)" % ( data.nice_size( dataset.get_size() ) )
- def get_mime(self):
- """Returns the mime type of the datatype"""
- return 'application/zip'
-
-class Txtseq( data.Data ):
- """Class describing a zip archive of text sequence files"""
- file_ext = "txtseq.zip"
- def set_peek( self, dataset ):
- if not dataset.dataset.purged:
- zip_file = zipfile.ZipFile( dataset.file_name, "r" )
- num_files = len( zip_file.namelist() )
- dataset.peek = "Archive of %s text sequence files" % ( str( num_files ) )
- dataset.blurb = data.nice_size( dataset.get_size() )
- else:
- dataset.peek = 'file does not exist'
- dataset.blurb = 'file purged from disk'
- def display_peek(self, dataset):
- try:
- return dataset.peek
- except:
- return "Text sequence file archive (%s)" % ( data.nice_size( dataset.get_size() ) )
- def get_mime(self):
- """Returns the mime type of the datatype"""
- return 'application/zip'
-
class Image( data.Data ):
"""Class describing an image"""
def set_peek( self, dataset ):
@@ -236,47 +160,3 @@ class Laj( data.Text ):
return dataset.peek
except:
return "peek unavailable"
-
-class Bam( data.Binary ):
- """Class describing a BAM binary file"""
- file_ext = "bam"
- MetadataElement( name="bam_index", desc="BAM Index File", param=metadata.FileParameter, readonly=True, no_value=None, visible=False, optional=True )
- def init_meta( self, dataset, copy_from=None ):
- data.Binary.init_meta( self, dataset, copy_from=copy_from )
- def set_meta( self, dataset, overwrite = True, **kwd ):
- """
- Sets index for BAM file.
- """
- index_file = dataset.metadata.bam_index
- if not index_file:
- index_file = dataset.metadata.spec['bam_index'].param.new_file( dataset = dataset )
- tmp_dir = tempfile.gettempdir()
- tmpf1 = tempfile.NamedTemporaryFile(dir=tmp_dir)
- tmpf1bai = '%s.bai' % tmpf1.name
- try:
- os.system('cd %s' % tmp_dir)
- os.system('cp %s %s' % (dataset.file_name, tmpf1.name))
- os.system('samtools index %s' % tmpf1.name)
- os.system('cp %s %s' % (tmpf1bai, index_file.file_name))
- except Exception, ex:
- sys.stderr.write('There was a problem creating the index for the BAM file\n%s\n' + str(ex))
- tmpf1.close()
- if os.path.exists(tmpf1bai):
- os.remove(tmpf1bai)
- dataset.metadata.bam_index = index_file
- def set_peek( self, dataset ):
- if not dataset.dataset.purged:
- export_url = "/history_add_to?" + urlencode({'history_id':dataset.history_id,'ext':'bam','name':'bam alignments','info':'Alignments file','dbkey':dataset.dbkey})
- dataset.peek = "Binary bam alignments file"
- dataset.blurb = data.nice_size( dataset.get_size() )
- else:
- dataset.peek = 'file does not exist'
- dataset.blurb = 'file purged from disk'
- def display_peek(self, dataset):
- try:
- return dataset.peek
- except:
- return "Binary bam alignments file (%s)" % ( data.nice_size( dataset.get_size() ) )
- def get_mime(self):
- """Returns the mime type of the datatype"""
- return 'application/octet-stream'
diff --git a/lib/galaxy/datatypes/metadata.py b/lib/galaxy/datatypes/metadata.py
index 6376531d9da..07363243d83 100644
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -509,7 +509,7 @@ class JobExternalOutputMetadataWrapper( object ):
# need to make different keys for them, since ids can overlap
return "%s_%d" % ( dataset.__class__.__name__, dataset.id )
def setup_external_metadata( self, datasets, sa_session, exec_dir=None, tmp_dir=None, dataset_files_path=None,
- output_fnames=None, config_root=None, datatypes_config=None, kwds={} ):
+ output_fnames=None, config_root=None, datatypes_config=None, job_metadata=None, kwds={} ):
#fill in metadata_files_dict and return the command with args required to set metadata
def __metadata_files_list_to_cmd_line( metadata_files ):
def __get_filename_override():
@@ -564,7 +564,7 @@ class JobExternalOutputMetadataWrapper( object ):
sa_session.flush()
metadata_files_list.append( metadata_files )
#return command required to build
- return "%s %s %s %s %s %s" % ( os.path.join( exec_dir, 'set_metadata.sh' ), dataset_files_path, tmp_dir, config_root, datatypes_config, " ".join( map( __metadata_files_list_to_cmd_line, metadata_files_list ) ) )
+ return "%s %s %s %s %s %s %s" % ( os.path.join( exec_dir, 'set_metadata.sh' ), dataset_files_path, tmp_dir, config_root, datatypes_config, job_metadata, " ".join( map( __metadata_files_list_to_cmd_line, metadata_files_list ) ) )
def external_metadata_set_successfully( self, dataset, sa_session ):
metadata_files = self.get_output_filenames_by_dataset( dataset, sa_session )
diff --git a/lib/galaxy/datatypes/registry.py b/lib/galaxy/datatypes/registry.py
index 76d8939f7ff..a49444e6cae 100644
--- a/lib/galaxy/datatypes/registry.py
+++ b/lib/galaxy/datatypes/registry.py
@@ -3,7 +3,7 @@ Provides mapping between extensions and datatypes, mime-types, etc.
"""
import os, tempfile
import logging
-import data, tabular, interval, images, sequence, qualityscore, genetics, xml, coverage, tracks, chrominfo
+import data, tabular, interval, images, sequence, qualityscore, genetics, xml, coverage, tracks, chrominfo, binary
import galaxy.util
from galaxy.util.odict import odict
@@ -109,11 +109,11 @@ class Registry( object ):
#default values
if len(self.datatypes_by_extension) < 1:
self.datatypes_by_extension = {
- 'ab1' : images.Ab1(),
+ 'ab1' : binary.Ab1(),
'axt' : sequence.Axt(),
- 'bam' : images.Bam(),
+ 'bam' : binary.Bam(),
'bed' : interval.Bed(),
- 'binseq.zip' : images.Binseq(),
+ 'binseq.zip' : binary.Binseq(),
'blastxml' : xml.BlastXml(),
'coverage' : coverage.LastzCoverage(),
'customtrack' : interval.CustomTrack(),
@@ -132,12 +132,12 @@ class Registry( object ):
'qualsolexa' : qualityscore.QualityScoreSolexa(),
'qual454' : qualityscore.QualityScore454(),
'sam' : tabular.Sam(),
- 'scf' : images.Scf(),
- 'sff' : data.Sff(),
+ 'scf' : binary.Scf(),
+ 'sff' : binary.Sff(),
'tabular' : tabular.Tabular(),
'taxonomy' : tabular.Taxonomy(),
'txt' : data.Text(),
- 'txtseq.zip' : images.Txtseq(),
+ 'txtseq.zip' : data.Txtseq(),
'wig' : interval.Wiggle()
}
self.mimetypes_by_extension = {
@@ -174,7 +174,7 @@ class Registry( object ):
# because some formats are much more flexibly defined than others.
if len(self.sniff_order) < 1:
self.sniff_order = [
- data.Sff(),
+ binary.Sff(),
xml.BlastXml(),
sequence.Maf(),
sequence.Lav(),
diff --git a/lib/galaxy/datatypes/tracks.py b/lib/galaxy/datatypes/tracks.py
index ed5b534aba6..2c4938c06ac 100644
--- a/lib/galaxy/datatypes/tracks.py
+++ b/lib/galaxy/datatypes/tracks.py
@@ -3,10 +3,7 @@ Datatype classes for tracks/track views within galaxy.
"""
import data
-import logging
-import re
-import binascii
-from cgi import escape
+import tabular, binascii, logging
from galaxy.datatypes.metadata import MetadataElement
from galaxy.datatypes import metadata
import galaxy.model
@@ -17,7 +14,7 @@ from galaxy.util.hash_util import *
log = logging.getLogger(__name__)
-class GeneTrack( data.Binary ):
+class GeneTrack( tabular.Tabular ):
file_ext = "genetrack"
MetadataElement( name="genetrack", default="data.genetrack", desc="HDF index", readonly=True, visible=True, no_value=0 )
@@ -27,7 +24,7 @@ class GeneTrack( data.Binary ):
super( GeneTrack, self ).__init__( **kwargs )
self.add_display_app( 'genetrack', 'View in', '', 'genetrack_link' )
def get_display_links( self, dataset, type, app, base_url, target_frame='galaxy_main', **kwd ):
- return data.Binary.get_display_links( self, dataset, type, app, base_url, target_frame=target_frame, **kwd )
+ return data.Data.get_display_links( self, dataset, type, app, base_url, target_frame=target_frame, **kwd )
def genetrack_link( self, hda, type, app, base_url ):
ret_val = []
if hda.has_data:
diff --git a/lib/galaxy/jobs/__init__.py b/lib/galaxy/jobs/__init__.py
index 73fa0096612..ce2197272b4 100644
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -139,10 +139,15 @@ class JobQueue( object ):
JobWrapper( job, None, self ).fail( 'This tool was disabled before the job completed. Please contact your Galaxy administrator, or' )
elif job.job_runner_name is None:
log.debug( "no runner: %s is still in queued state, adding to the jobs queue" %job.id )
- self.queue.put( ( job.id, job.tool_id ) )
+ if self.track_jobs_in_database:
+ job.state = model.Job.states.NEW
+ else:
+ self.queue.put( ( job.id, job.tool_id ) )
else:
job_wrapper = JobWrapper( job, self.app.toolbox.tools_by_id[ job.tool_id ], self )
self.dispatcher.recover( job, job_wrapper )
+ if self.sa_session.dirty:
+ self.sa_session.flush()
def __monitor( self ):
"""
@@ -526,6 +531,7 @@ class JobWrapper( object ):
# If the tool was expected to set the extension, attempt to retrieve it
if dataset.ext == 'auto':
dataset.extension = context.get( 'ext', 'data' )
+ dataset.init_meta( copy_from=dataset )
#if a dataset was copied, it won't appear in our dictionary:
#either use the metadata from originating output dataset, or call set_meta on the copies
#it would be quicker to just copy the metadata from the originating output dataset,
@@ -715,14 +721,15 @@ class JobWrapper( object ):
for outfile in [ str( o ) for o in output_paths ]:
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 ):
+ def setup_external_metadata( self, exec_dir = None, tmp_dir = None, dataset_files_path = None, config_root = None, datatypes_config = None, set_extension = True, **kwds ):
# extension could still be 'auto' if this is the upload tool.
job = self.sa_session.query( 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' )
- self.sa_session.flush()
+ if set_extension:
+ 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' )
+ self.sa_session.flush()
if tmp_dir is None:
#this dir should should relative to the exec_dir
tmp_dir = self.app.config.new_file_path
@@ -739,6 +746,7 @@ class JobWrapper( object ):
dataset_files_path = dataset_files_path,
config_root = config_root,
datatypes_config = datatypes_config,
+ job_metadata = os.path.join( self.working_directory, TOOL_PROVIDED_JOB_METADATA_FILE ),
**kwds )
class DefaultJobDispatcher( object ):
diff --git a/lib/galaxy/jobs/runners/local.py b/lib/galaxy/jobs/runners/local.py
index e9de560bb10..a2f10cbc1c3 100644
--- a/lib/galaxy/jobs/runners/local.py
+++ b/lib/galaxy/jobs/runners/local.py
@@ -106,7 +106,9 @@ class LocalJobRunner( object ):
#this is terminatable when output dataset/job is deleted
#so that long running set_meta()s can be cancelled without having to reboot the server
if job_wrapper.get_state() not in [ model.Job.states.ERROR, model.Job.states.DELETED ] and self.app.config.set_metadata_externally and job_wrapper.output_paths:
- external_metadata_script = job_wrapper.setup_external_metadata( output_fnames = job_wrapper.get_output_fnames(), kwds = { 'overwrite' : False } ) #we don't want to overwrite metadata that was copied over in init_meta(), as per established behavior
+ external_metadata_script = job_wrapper.setup_external_metadata( output_fnames = job_wrapper.get_output_fnames(),
+ set_extension = True,
+ kwds = { 'overwrite' : False } ) #we don't want to overwrite metadata that was copied over in init_meta(), as per established behavior
log.debug( 'executing external set_meta script for job %d: %s' % ( job_wrapper.job_id, external_metadata_script ) )
external_metadata_proc = subprocess.Popen( args = external_metadata_script,
shell = True,
diff --git a/lib/galaxy/jobs/runners/pbs.py b/lib/galaxy/jobs/runners/pbs.py
index 835424d7fe9..921b1a605d8 100644
--- a/lib/galaxy/jobs/runners/pbs.py
+++ b/lib/galaxy/jobs/runners/pbs.py
@@ -29,7 +29,6 @@ if [ "$GALAXY_LIB" != "None" ]; then
fi
cd %s
%s
-%s
"""
pbs_symlink_template = """#!/bin/sh
@@ -178,7 +177,9 @@ class PBSJobRunner( object ):
pbs_queue_name = self.determine_pbs_queue( runner_url )
c = pbs.pbs_connect( pbs_server_name )
if c <= 0:
- raise Exception( "Connection to PBS server for submit failed" )
+ job_wrapper.fail( "Unable to queue job for execution. Resubmitting the job may succeed." )
+ log.error( "Connection to PBS server for submit failed" )
+ return
# define job attributes
ofile = "%s/%s.o" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
@@ -221,11 +222,15 @@ class PBSJobRunner( object ):
if self.app.config.pbs_stage_path != '':
script = pbs_symlink_template % (job_wrapper.galaxy_lib_dir, " ".join(job_wrapper.get_input_fnames() + output_files), self.app.config.pbs_stage_path, exec_dir, command_line)
else:
+ script = pbs_template % ( job_wrapper.galaxy_lib_dir, exec_dir, command_line )
if self.app.config.set_metadata_externally:
- external_metadata_script = job_wrapper.setup_external_metadata( exec_dir = os.path.abspath( os.getcwd() ), tmp_dir = self.app.config.new_file_path, dataset_files_path = self.app.model.Dataset.file_path, output_fnames = output_fnames, kwds = { 'overwrite' : False } ) #we don't want to overwrite metadata that was copied over in init_meta(), as per established behavior
- else:
- external_metadata_script = ""
- script = pbs_template % ( job_wrapper.galaxy_lib_dir, exec_dir, command_line, external_metadata_script )
+ script += "cd %s\n" % os.path.abspath( os.getcwd() )
+ script += "%s\n" % job_wrapper.setup_external_metadata( exec_dir = os.path.abspath( os.getcwd() ),
+ tmp_dir = self.app.config.new_file_path,
+ dataset_files_path = self.app.model.Dataset.file_path,
+ output_fnames = output_fnames,
+ set_extension = False,
+ kwds = { 'overwrite' : False } ) #we don't want to overwrite metadata that was copied over in init_meta(), as per established behavior
job_file = "%s/%s.sh" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
fh = file(job_file, "w")
fh.write(script)
diff --git a/lib/galaxy/tools/actions/metadata.py b/lib/galaxy/tools/actions/metadata.py
index 7cbb6a1705a..420812bac56 100644
--- a/lib/galaxy/tools/actions/metadata.py
+++ b/lib/galaxy/tools/actions/metadata.py
@@ -41,6 +41,7 @@ class SetMetadataToolAction( ToolAction ):
output_fnames = None,
config_root = None,
datatypes_config = None,
+ job_metadata = None,
kwds = { 'overwrite' : True } )
incoming[ '__SET_EXTERNAL_METADATA_COMMAND_LINE__' ] = cmd_line
for name, value in tool.params_to_strings( incoming, trans.app ).iteritems():
diff --git a/lib/galaxy/web/controllers/dataset.py b/lib/galaxy/web/controllers/dataset.py
index 762673265ea..6fde6a8e158 100644
--- a/lib/galaxy/web/controllers/dataset.py
+++ b/lib/galaxy/web/controllers/dataset.py
@@ -20,25 +20,38 @@ GALAXY TOOL ERROR REPORT
This error report was sent from the Galaxy instance hosted on the server
"${host}"
-----------------------------------------------------------------------------
-This is in reference to output dataset ${dataset_id}.
+This is in reference to dataset id ${dataset_id} from history id ${history_id}
+-----------------------------------------------------------------------------
+You should be able to view the history containing the related history item
+
+${hid}: ${history_item_name}
+
+by logging in as a Galaxy admin user to the Galaxy instance referenced above
+and pointing your browser to the following link.
+
+${history_view_link}
-----------------------------------------------------------------------------
The user '${email}' provided the following information:
+
${message}
-----------------------------------------------------------------------------
job id: ${job_id}
-tool id: ${tool_id}
+tool id: ${job_tool_id}
+-----------------------------------------------------------------------------
+job command line:
+${job_command_line}
-----------------------------------------------------------------------------
job stderr:
-${stderr}
+${job_stderr}
-----------------------------------------------------------------------------
job stdout:
-${stdout}
+${job_stdout}
-----------------------------------------------------------------------------
job info:
-${info}
+${job_info}
-----------------------------------------------------------------------------
job traceback:
-${traceback}
+${job_traceback}
-----------------------------------------------------------------------------
(This is an automated message).
"""
@@ -103,41 +116,45 @@ class DatasetInterface( BaseController ):
@web.expose
def errors( self, trans, id ):
- dataset = trans.sa_session.query( model.HistoryDatasetAssociation ).get( id )
- return trans.fill_template( "dataset/errors.mako", dataset=dataset )
-
+ hda = trans.sa_session.query( model.HistoryDatasetAssociation ).get( id )
+ return trans.fill_template( "dataset/errors.mako", hda=hda )
@web.expose
def stderr( self, trans, id ):
dataset = trans.sa_session.query( model.HistoryDatasetAssociation ).get( id )
job = dataset.creating_job_associations[0].job
trans.response.set_content_type( 'text/plain' )
return job.stderr
-
@web.expose
def report_error( self, trans, id, email='', message="" ):
smtp_server = trans.app.config.smtp_server
if smtp_server is None:
- return trans.show_error_message( "Sorry, mail is not configured for this galaxy instance" )
+ return trans.show_error_message( "Mail is not configured for this galaxy instance" )
to_address = trans.app.config.error_email_to
if to_address is None:
- return trans.show_error_message( "Sorry, error reporting has been disabled for this galaxy instance" )
+ return trans.show_error_message( "Error reporting has been disabled for this galaxy instance" )
# Get the dataset and associated job
- dataset = trans.sa_session.query( model.HistoryDatasetAssociation ).get( id )
- job = dataset.creating_job_associations[0].job
+ hda = trans.sa_session.query( model.HistoryDatasetAssociation ).get( id )
+ job = hda.creating_job_associations[0].job
# Get the name of the server hosting the Galaxy instance from which this report originated
host = trans.request.host
+ history_view_link = "%s/history/view?id=%s" % ( str( host ), trans.security.encode_id( hda.history_id ) )
# Build the email message
msg = MIMEText( string.Template( error_report_template )
.safe_substitute( host=host,
- dataset_id=dataset.id,
- email=email,
- message=message,
+ dataset_id=hda.dataset_id,
+ history_id=hda.history_id,
+ hid=hda.hid,
+ history_item_name=hda.get_display_name(),
+ history_view_link=history_view_link,
job_id=job.id,
- tool_id=job.tool_id,
- stderr=job.stderr,
- stdout=job.stdout,
- traceback=job.traceback,
- info=job.info ) )
+ job_tool_id=job.tool_id,
+ job_command_line=job.command_line,
+ job_stderr=job.stderr,
+ job_stdout=job.stdout,
+ job_info=job.info,
+ job_traceback=job.traceback,
+ email=email,
+ message=message ) )
frm = to_address
# Check email a bit
email = email.strip()
diff --git a/lib/galaxy/web/controllers/forms.py b/lib/galaxy/web/controllers/forms.py
index 96eb1d8a9c9..b6485339d53 100644
--- a/lib/galaxy/web/controllers/forms.py
+++ b/lib/galaxy/web/controllers/forms.py
@@ -8,9 +8,71 @@ from galaxy.tools.parameters.basic import parameter_types
from elementtree.ElementTree import XML, Element
from galaxy.util.odict import odict
import copy
+from galaxy.web.framework.helpers import time_ago, iff, grids
log = logging.getLogger( __name__ )
+class FormsGrid( grids.Grid ):
+ # Custom column types
+ class NameColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, form):
+ return form.latest_form.name
+ class DescriptionColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, form):
+ return form.latest_form.desc
+ class TypeColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, form):
+ return form.latest_form.type
+ class DeletedColumn( grids.GridColumn ):
+ def get_accepted_filters( self ):
+ """ Returns a list of accepted filters for this column. """
+ accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" }
+ accepted_filters = []
+ for label, val in accepted_filter_labels_and_vals.items():
+ args = { self.key: val }
+ accepted_filters.append( grids.GridColumnFilter( label, args) )
+ return accepted_filters
+ # Grid definition
+ title = "Forms"
+ template = "admin/forms/grid.mako"
+ model_class = model.FormDefinitionCurrent
+ default_sort_key = "-create_time"
+ num_rows_per_page = 50
+ preserve_state = True
+ use_paging = True
+ default_filter = dict( deleted="False" )
+ columns = [
+ NameColumn( "Name",
+ key="name",
+ model_class=model.FormDefinition,
+ link=( lambda item: iff( item.deleted, None, dict( operation="view", id=item.id ) ) ),
+ attach_popup=True,
+ filterable="advanced" ),
+ DescriptionColumn( "Description",
+ key='desc',
+ model_class=model.FormDefinition,
+ filterable="advanced" ),
+ TypeColumn( "Type" ),
+ DeletedColumn( "Deleted",
+ key="deleted",
+ visible=False,
+ filterable="advanced" )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+ operations = [
+ grids.GridOperation( "Edit", allow_multiple=False, condition=( lambda item: not item.deleted ) ),
+ grids.GridOperation( "Delete", allow_multiple=True, condition=( lambda item: not item.deleted ) ),
+ grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ) ),
+ ]
+ global_actions = [
+ grids.GridAction( "Create new form", dict( controller='forms',
+ action='new' ) )
+ ]
+
class Forms( BaseController ):
# Empty form field
empty_field = { 'label': '',
@@ -20,38 +82,38 @@ class Forms( BaseController ):
'type': BaseField.form_field_types()[0],
'selectlist': [],
'layout': 'none' }
+ forms_grid = FormsGrid()
+
@web.expose
@web.require_admin
- def index( self, trans, **kwd ):
- params = util.Params( kwd )
- msg = util.restore_text( params.get( 'msg', '' ) )
- messagetype = params.get( 'messagetype', 'done' )
- return trans.fill_template( "/sample/index.mako",
- default_action=params.get( 'default_action', None ),
- msg=msg,
- messagetype=messagetype )
- @web.expose
- @web.require_admin
- def manage( self, trans, **kwd ):
- params = util.Params( kwd )
- msg = util.restore_text( params.get( 'msg', '' ) )
- messagetype = params.get( 'messagetype', 'done' )
- show_filter = params.get( 'show_filter', 'Active' )
- return self._show_forms_list(trans, msg, messagetype, show_filter)
- def _show_forms_list(self, trans, msg, messagetype, show_filter='Active'):
- all_forms = trans.sa_session.query( trans.app.model.FormDefinitionCurrent )
- if show_filter == 'All':
- forms_list = all_forms
- elif show_filter == 'Deleted':
- forms_list = [form for form in all_forms if form.deleted]
- else:
- forms_list = [form for form in all_forms if not form.deleted]
- return trans.fill_template( '/admin/forms/manage_forms.mako',
- fdc_list=forms_list,
- all_forms=all_forms,
- show_filter=show_filter,
- msg=msg,
- messagetype=messagetype )
+ def manage( self, trans, **kwd ):
+ if 'operation' in kwd:
+ operation = kwd['operation'].lower()
+ if not kwd.get( 'id', None ):
+ return trans.response.send_redirect( web.url_for( controller='forms',
+ action='manage',
+ status='error',
+ message="Invalid form ID") )
+ if operation == "view":
+ return self.__view( trans, **kwd )
+ elif operation == "delete":
+ return self.__delete( trans, **kwd )
+ elif operation == "undelete":
+ return self.__undelete( trans, **kwd )
+ elif operation == "edit":
+ return self.__edit( trans, **kwd )
+ return self.forms_grid( trans, **kwd )
+ def __view(self, trans, **kwd):
+ try:
+ fdc = trans.sa_session.query( trans.app.model.FormDefinitionCurrent )\
+ .get( trans.security.decode_id(kwd['id']) )
+ except:
+ return trans.response.send_redirect( web.url_for( controller='forms',
+ action='manage',
+ msg='Invalid form',
+ messagetype='error' ) )
+ return trans.fill_template( '/admin/forms/show_form_read_only.mako',
+ form=fdc.latest_form )
def __form_types_widget(self, trans, selected='none'):
form_type_selectbox = SelectField( 'form_type_selectbox',
refresh_on_change=True,
@@ -86,13 +148,14 @@ class Forms( BaseController ):
self.__get_saved_form( fd )
if self.__imported_from_file:
return trans.response.send_redirect( web.url_for( controller='forms',
- action='edit',
- show_form=True,
- form_id=fd.id) )
+ action='manage',
+ operation='edit',
+ id=trans.security.encode_id(fd.current.id)) )
else:
return trans.response.send_redirect( web.url_for( controller='forms',
- action='edit',
- form_id=fd.id,
+ action='manage',
+ operation='edit',
+ id=trans.security.encode_id(fd.current.id),
add_field_button='Add field',
name=fd.name,
description=fd.desc,
@@ -105,35 +168,43 @@ class Forms( BaseController ):
inputs=inputs,
msg=msg,
messagetype=messagetype )
- @web.expose
- @web.require_admin
- def delete( self, trans, **kwd ):
- params = util.Params( kwd )
- msg = util.restore_text( params.get( 'msg', '' ) )
- messagetype = params.get( 'messagetype', 'done' )
- fd = trans.sa_session.query( trans.app.model.FormDefinition ).get( int( util.restore_text( params.form_id ) ) )
- fd.form_definition_current.deleted = True
- trans.sa_session.add( fd.form_definition_current )
- trans.sa_session.flush()
- return self._show_forms_list(trans,
- msg='The form definition named %s is deleted.' % fd.name,
- messagetype='done')
- @web.expose
- @web.require_admin
- def undelete( self, trans, **kwd ):
- params = util.Params( kwd )
- msg = util.restore_text( params.get( 'msg', '' ) )
- messagetype = params.get( 'messagetype', 'done' )
- fd = trans.sa_session.query( trans.app.model.FormDefinition ).get( int( util.restore_text( params.form_id ) ) )
- fd.form_definition_current.deleted = False
- trans.sa_session.add( fd.form_definition_current )
- trans.sa_session.flush()
- return self._show_forms_list(trans,
- msg='The form definition named %s is undeleted.' % fd.name,
- messagetype='done')
- @web.expose
- @web.require_admin
- def edit( self, trans, **kwd ):
+ def __delete( self, trans, **kwd ):
+ id_list = util.listify( kwd['id'] )
+ delete_failed = []
+ for id in id_list:
+ try:
+ fdc = trans.sa_session.query( trans.app.model.FormDefinitionCurrent ).get( trans.security.decode_id(id) )
+ except:
+ return trans.response.send_redirect( web.url_for( controller='forms',
+ action='manage',
+ message='Invalid form',
+ status='error' ) )
+ fdc.deleted = True
+ trans.sa_session.add( fdc )
+ trans.sa_session.flush()
+ return trans.response.send_redirect( web.url_for( controller='forms',
+ action='manage',
+ message='%i form(s) is deleted.' % len(id_list),
+ status='done') )
+ def __undelete( self, trans, **kwd ):
+ id_list = util.listify( kwd['id'] )
+ delete_failed = []
+ for id in id_list:
+ try:
+ fdc = trans.sa_session.query( trans.app.model.FormDefinitionCurrent ).get( trans.security.decode_id(id) )
+ except:
+ return trans.response.send_redirect( web.url_for( controller='forms',
+ action='manage',
+ message='Invalid form',
+ status='error' ) )
+ fdc.deleted = False
+ trans.sa_session.add( fdc )
+ trans.sa_session.flush()
+ return trans.response.send_redirect( web.url_for( controller='forms',
+ action='manage',
+ message='%i form(s) is undeleted.' % len(id_list),
+ status='done') )
+ def __edit( self, trans, **kwd ):
'''
This callback method is for handling all the editing functions like
renaming fields, adding/deleting fields, changing fields attributes.
@@ -142,17 +213,28 @@ class Forms( BaseController ):
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
try:
- fd = trans.sa_session.query( trans.app.model.FormDefinition ).get( int( params.get( 'form_id', None ) ) )
+ fdc = trans.sa_session.query( trans.app.model.FormDefinitionCurrent ).get( trans.security.decode_id(kwd['id']) )
except:
return trans.response.send_redirect( web.url_for( controller='forms',
action='manage',
- msg='Invalid form',
- messagetype='error' ) )
+ message='Invalid form',
+ status='error' ) )
+ fd = fdc.latest_form
#
- # Show the form for editing
+ # Save changes
#
- if params.get( 'show_form', False ):
+ if params.get( 'save_changes_button', False ):
+ fd_new, msg = self.__save_form( trans, fdc_id=fd.form_definition_current.id, **kwd )
+ # if validation error encountered while saving the form, show the
+ # unsaved form, with the error message
+ if not fd_new:
+ current_form = self.__get_form( trans, **kwd )
+ return self.__show( trans=trans, form=fd, current_form=current_form,
+ msg=msg, messagetype='error', **kwd )
+ # everything went fine. form saved successfully. Show the saved form
+ fd = fd_new
current_form = self.__get_saved_form( fd )
+ msg = "The form '%s' has been updated with the changes." % fd.name
return self.__show( trans=trans, form=fd, current_form=current_form,
msg=msg, messagetype=messagetype, **kwd )
#
@@ -193,31 +275,6 @@ class Forms( BaseController ):
return self.__show( trans=trans, form=fd, current_form=current_form,
msg=msg, messagetype=messagetype, **kwd )
#
- # Save changes
- #
- elif params.get( 'save_changes_button', False ):
- fd_new, msg = self.__save_form( trans, fdc_id=fd.form_definition_current.id, **kwd )
- # if validation error encountered while saving the form, show the
- # unsaved form, with the error message
- if not fd_new:
- current_form = self.__get_form( trans, **kwd )
- return self.__show( trans=trans, form=fd, current_form=current_form,
- msg=msg, messagetype='error', **kwd )
- # everything went fine. form saved successfully. Show the saved form
- fd = fd_new
- current_form = self.__get_saved_form( fd )
- msg = "The form '%s' has been updated with the changes." % fd.name
- return self.__show( trans=trans, form=fd, current_form=current_form,
- msg=msg, messagetype=messagetype, **kwd )
- #
- # Show form read-only
- #
- elif params.get( 'read_only', False ):
- return trans.fill_template( '/admin/forms/show_form_read_only.mako',
- form=fd,
- msg=msg,
- messagetype=messagetype )
- #
# Add SelectField option
#
elif 'Add' in kwd.values():
@@ -234,6 +291,13 @@ class Forms( BaseController ):
current_form = self.__get_form( trans, **kwd )
return self.__show( trans=trans, form=fd, current_form=current_form,
msg=msg, messagetype=messagetype, **kwd )
+ #
+ # Show the form for editing
+ #
+ else:
+ current_form = self.__get_saved_form( fd )
+ return self.__show( trans=trans, form=fd, current_form=current_form,
+ msg=msg, messagetype=messagetype, **kwd )
def __add_selectbox_option( self, trans, fd, msg, messagetype, **kwd ):
'''
diff --git a/lib/galaxy/web/controllers/history.py b/lib/galaxy/web/controllers/history.py
index eca58b94811..5fca0008392 100644
--- a/lib/galaxy/web/controllers/history.py
+++ b/lib/galaxy/web/controllers/history.py
@@ -87,7 +87,7 @@ class HistoryListGrid( grids.Grid ):
# Grid definition
title = "Saved Histories"
model_class = model.History
- template='/history/grid.mako'
+ template='/grid_base.mako'
default_sort_key = "-create_time"
columns = [
NameColumn( "Name", key="name", model_class=model.History,
@@ -110,14 +110,14 @@ class HistoryListGrid( grids.Grid ):
)
operations = [
- grids.GridOperation( "Switch", allow_multiple=False, condition=( lambda item: not item.deleted ) ),
- grids.GridOperation( "Share", condition=( lambda item: not item.deleted ) ),
- grids.GridOperation( "Unshare", condition=( lambda item: not item.deleted ) ),
- grids.GridOperation( "Rename", condition=( lambda item: not item.deleted ) ),
- grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ) ),
- grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ) ),
- grids.GridOperation( "Enable import via link", condition=( lambda item: item.deleted ) ),
- grids.GridOperation( "Disable import via link", condition=( lambda item: item.deleted ) )
+ grids.GridOperation( "Switch", allow_multiple=False, condition=( lambda item: not item.deleted ), async_compatible=True ),
+ grids.GridOperation( "Share", condition=( lambda item: not item.deleted ), async_compatible=False ),
+ grids.GridOperation( "Unshare", condition=( lambda item: not item.deleted ), async_compatible=False ),
+ grids.GridOperation( "Rename", condition=( lambda item: not item.deleted ), async_compatible=False ),
+ grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ), async_compatible=True ),
+ grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ), async_compatible=True ),
+ grids.GridOperation( "Enable import via link", condition=( lambda item: item.deleted ), async_compatible=True ),
+ grids.GridOperation( "Disable import via link", condition=( lambda item: item.deleted ), async_compatible=True )
]
standard_filters = [
grids.GridColumnFilter( "Active", args=dict( deleted=False ) ),
@@ -262,7 +262,7 @@ class HistoryController( BaseController ):
n_deleted += 1
status = SUCCESS
if n_deleted:
- message_parts.append( "Deleted %d histories. " % n_deleted )
+ message_parts.append( "Deleted %d %s. " % ( n_deleted, iff( n_deleted != 1, "histories", "history" ) ) )
if deleted_current:
message_parts.append( "Your active history was deleted, a new empty history is now active. " )
status = INFO
@@ -290,7 +290,7 @@ class HistoryController( BaseController ):
status = SUCCESS
message_parts = []
if n_undeleted:
- message_parts.append( "Undeleted %d histories." % n_undeleted )
+ message_parts.append( "Undeleted %d %s. " % ( n_undeleted, iff( n_undeleted != 1, "histories", "history" ) ) )
if n_already_purged:
message_parts.append( "%d histories have already been purged and cannot be undeleted." % n_already_purged )
status = WARNING
@@ -438,23 +438,20 @@ class HistoryController( BaseController ):
Warning! If you import this history, you will lose your current
history. Click here to confirm.
""" % web.url_for( id=id, confirm=True ) )
-
@web.expose
def view( self, trans, id=None ):
"""View a history. If a history is importable, then it is viewable by any user."""
-
# Get history to view.
if not id:
return trans.show_error_message( "You must specify a history you want to view." )
history_to_view = get_history( trans, id, False)
-
# Integrity checks.
if not history_to_view:
- return trans.show_error_message( "The specified history does not exist.")
+ return trans.show_error_message( "The specified history does not exist." )
+ # Admin users can view any history
# TODO: Use a new flag to determine if history is viewable?
- if not history_to_view.importable:
- error( "The owner of this history has not published this history." )
-
+ if not trans.user_is_admin and not history_to_view.importable:
+ error( "Either you are not allowed to view this history or the owner of this history has not published it." )
# View history.
query = trans.sa_session.query( model.HistoryDatasetAssociation ) \
.filter( model.HistoryDatasetAssociation.history == history_to_view ) \
@@ -469,7 +466,6 @@ class HistoryController( BaseController ):
datasets = query.all(),
user_owns_history = user_owns_history,
show_deleted = False )
-
@web.expose
@web.require_login( "share histories with other users" )
def share( self, trans, id=None, email="", **kwd ):
diff --git a/lib/galaxy/web/controllers/library_common.py b/lib/galaxy/web/controllers/library_common.py
index d3ac8e0b588..60222457272 100644
--- a/lib/galaxy/web/controllers/library_common.py
+++ b/lib/galaxy/web/controllers/library_common.py
@@ -117,7 +117,7 @@ class LibraryCommon( BaseController ):
uploaded_dataset.link_data_only = True
uploaded_dataset.data.file_name = os.path.abspath( path )
trans.sa_session.add( uploaded_dataset.data )
- trans.sa_session.data.flush()
+ trans.sa_session.flush()
return uploaded_dataset
def get_server_dir_uploaded_datasets( self, trans, params, full_dir, import_dir_desc, library_bunch, err_redirect, msg ):
files = []
diff --git a/lib/galaxy/web/controllers/page.py b/lib/galaxy/web/controllers/page.py
index 0923cef5ee8..5f8c0f63bc5 100644
--- a/lib/galaxy/web/controllers/page.py
+++ b/lib/galaxy/web/controllers/page.py
@@ -1,6 +1,7 @@
from galaxy.web.base.controller import *
from galaxy.web.framework.helpers import time_ago, grids
from galaxy.util.sanitize_html import sanitize_html
+from galaxy.util.odict import odict
import re
@@ -69,21 +70,66 @@ class PageAllPublishedGrid( grids.Grid ):
]
def apply_default_filter( self, trans, query, **kwargs ):
return query.filter_by( deleted=False, published=True )
-
-
-class NameColumn( grids.TextColumn ):
- def get_value(self, trans, grid, history):
- return history.get_display_name()
class HistorySelectionGrid( grids.Grid ):
+ # Custom columns.
+ class NameColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, history):
+ return history.get_display_name()
+
+ class DeletedColumn( grids.GridColumn ):
+ def get_accepted_filters( self ):
+ """ Returns a list of accepted filters for this column. """
+ accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" }
+ accepted_filters = []
+ for label, val in accepted_filter_labels_and_vals.items():
+ args = { self.key: val }
+ accepted_filters.append( grids.GridColumnFilter( label, args) )
+ return accepted_filters
+
+ class SharingColumn( grids.GridColumn ):
+ def filter( self, db_session, query, column_filter ):
+ """ Modify query to filter histories by sharing status. """
+ if column_filter == "All":
+ pass
+ elif column_filter:
+ if column_filter == "private":
+ query = query.filter( model.History.users_shared_with == None )
+ query = query.filter( model.History.importable == False )
+ elif column_filter == "shared":
+ query = query.filter( model.History.users_shared_with != None )
+ elif column_filter == "importable":
+ query = query.filter( model.History.importable == True )
+ return query
+ def get_accepted_filters( self ):
+ """ Returns a list of accepted filters for this column. """
+ accepted_filter_labels_and_vals = odict()
+ accepted_filter_labels_and_vals["private"] = "private"
+ accepted_filter_labels_and_vals["shared"] = "shared"
+ accepted_filter_labels_and_vals["importable"] = "importable"
+ accepted_filter_labels_and_vals["all"] = "All"
+ accepted_filters = []
+ for label, val in accepted_filter_labels_and_vals.items():
+ args = { self.key: val }
+ accepted_filters.append( grids.GridColumnFilter( label, args) )
+ return accepted_filters
+
# Grid definition.
title = "Saved Histories"
+ template = "grid_base_async.mako"
+ async_template = "grid_body_async.mako"
model_class = model.History
+ default_filter = { "deleted" : "False" , "shared" : "All" }
default_sort_key = "-update_time"
+ use_paging = True
+ num_rows_per_page = 5
columns = [
NameColumn( "Name", key="name", model_class=model.History, filterable="advanced" ),
grids.TagsColumn( "Tags", "tags", model.History, model.HistoryTagAssociation, filterable="advanced"),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
+ # Columns that are valid for filtering but are not visible.
+ DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ),
+ SharingColumn( "Shared", key="shared", visible=False, filterable="advanced" ),
]
columns.append(
grids.MulticolFilterColumn(
@@ -91,6 +137,8 @@ class HistorySelectionGrid( grids.Grid ):
cols_to_filter=[ columns[0], columns[1] ],
key="free-text-search", visible=False, filterable="standard" )
)
+ def apply_default_filter( self, trans, query, **kwargs ):
+ return query.filter_by( user=trans.user, purged=False )
class PageController( BaseController ):
@@ -268,4 +316,4 @@ class PageController( BaseController ):
@web.require_login("select a history from saved histories")
def list_histories_for_selection( self, trans, **kwargs ):
# Render the list view
- return self._history_selection_grid( trans, status=status, message=message, **kwargs )
\ No newline at end of file
+ return self._history_selection_grid( trans, **kwargs )
\ No newline at end of file
diff --git a/lib/galaxy/web/controllers/requests.py b/lib/galaxy/web/controllers/requests.py
index 2b938a6a362..75afe8ae6df 100644
--- a/lib/galaxy/web/controllers/requests.py
+++ b/lib/galaxy/web/controllers/requests.py
@@ -12,57 +12,109 @@ from cgi import escape, FieldStorage
log = logging.getLogger( __name__ )
-class RequestsListGrid( grids.Grid ):
+class RequestsGrid( grids.Grid ):
+ # Custom column types
+ class NameColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, request):
+ return request.name
+ class DescriptionColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, request):
+ return request.desc
+ class SamplesColumn( grids.GridColumn ):
+ def get_value(self, trans, grid, request):
+ return str(len(request.samples))
+ class TypeColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, request):
+ return request.type.name
+ class LastUpdateColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, request):
+ return request.update_time
+ class StateColumn( grids.GridColumn ):
+ def filter( self, db_session, query, column_filter ):
+ """ Modify query to filter request by state. """
+ if column_filter == "All":
+ return query
+ if column_filter:
+ query = query.filter( model.Request.state == column_filter )
+ return query
+ def get_accepted_filters( self ):
+ """ Returns a list of accepted filters for this column. """
+ accepted_filter_labels_and_vals = [ model.Request.states.UNSUBMITTED,
+ model.Request.states.SUBMITTED,
+ model.Request.states.COMPLETE,
+ "All"]
+ accepted_filters = []
+ for val in accepted_filter_labels_and_vals:
+ label = val.lower()
+ args = { self.key: val }
+ accepted_filters.append( grids.GridColumnFilter( label, args) )
+ return accepted_filters
+ class DeletedColumn( grids.GridColumn ):
+ def get_accepted_filters( self ):
+ """ Returns a list of accepted filters for this column. """
+ accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" }
+ accepted_filters = []
+ for label, val in accepted_filter_labels_and_vals.items():
+ args = { self.key: val }
+ accepted_filters.append( grids.GridColumnFilter( label, args) )
+ return accepted_filters
+ # Grid definition
title = "Sequencing Requests"
- template = '/requests/grid.mako'
+ template = 'requests/grid.mako'
model_class = model.Request
default_sort_key = "-create_time"
- show_filter = model.Request.states.UNSUBMITTED
+ num_rows_per_page = 50
+ preserve_state = True
+ use_paging = True
+ default_filter = dict( deleted="False", state=model.Request.states.UNSUBMITTED)
columns = [
- grids.GridColumn( "Name", key="name",
- link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ),
- attach_popup=True ),
- grids.GridColumn( "Description", key='desc'),
- grids.GridColumn( "Sample(s)", method='number_of_samples',
- link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ), ),
- grids.GridColumn( "Type", key="request_type_id", method='get_request_type'),
- grids.GridColumn( "Last update", key="update_time", format=time_ago ),
- grids.GridColumn( "State", key='state'),
+ NameColumn( "Name",
+ key="name",
+ model_class=model.Request,
+ link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ),
+ attach_popup=True,
+ filterable="advanced" ),
+ DescriptionColumn( "Description",
+ key='desc',
+ model_class=model.Request,
+ filterable="advanced" ),
+ SamplesColumn( "Sample(s)",
+ link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ), ),
+ TypeColumn( "Type" ),
+ LastUpdateColumn( "Last update",
+ format=time_ago ),
+ StateColumn( "State",
+ key='state',
+ filterable="advanced"),
+ DeletedColumn( "Deleted",
+ key="deleted",
+ visible=True,
+ filterable="advanced" )
]
+ columns.append( grids.MulticolFilterColumn( "Search",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
operations = [
grids.GridOperation( "Submit", allow_multiple=False, condition=( lambda item: not item.deleted and item.unsubmitted() and item.samples ) ),
grids.GridOperation( "Edit", allow_multiple=False, condition=( lambda item: not item.deleted and item.unsubmitted() ) ),
- grids.GridOperation( "Delete", allow_multiple=False, condition=( lambda item: not item.deleted and item.unsubmitted() ) ),
- grids.GridOperation( "Undelete", allow_multiple=False, condition=( lambda item: item.deleted ) )
+ grids.GridOperation( "Delete", allow_multiple=True, condition=( lambda item: not item.deleted and item.unsubmitted() ) ),
+ grids.GridOperation( "Undelete", allow_multiple=True, condition=( lambda item: item.deleted ) )
]
- standard_filters = [
- grids.GridColumnFilter( model.Request.states.UNSUBMITTED,
- args=dict( state=model.Request.states.UNSUBMITTED, deleted=False ) ),
- grids.GridColumnFilter( model.Request.states.SUBMITTED,
- args=dict( state=model.Request.states.SUBMITTED, deleted=False ) ),
- grids.GridColumnFilter( model.Request.states.COMPLETE, args=dict( state=model.Request.states.COMPLETE, deleted=False ) ),
- grids.GridColumnFilter( "Deleted", args=dict( deleted=True ) ),
- grids.GridColumnFilter( "All", args={} )
+ global_actions = [
+ grids.GridAction( "Create new request", dict( controller='requests',
+ action='new',
+ select_request_type='True' ) )
]
- #default_filter = dict( deleted=False )
- def get_current_item( self, trans ):
- return None
- def get_request_type(self, trans, request):
- return request.type.name
- def apply_default_filter( self, trans, query, **kwargs ):
- query = query.filter_by( user=trans.user )
- if self.default_filter:
- return query.filter_by( **self.default_filter )
- else:
- return query
- def number_of_samples(self, trans, request):
- return str(len(request.samples))
- def get_state(self, trans, request):
- return request.state
+ def apply_default_filter( self, trans, query, **kwd ):
+ return query.filter_by( user=trans.user )
+ def build_initial_query( self, session ):
+ return session.query( self.model_class )
class Requests( BaseController ):
- request_grid = RequestsListGrid()
+ request_grid = RequestsGrid()
@web.expose
@web.require_login( "create/submit sequencing requests" )
@@ -71,50 +123,43 @@ class Requests( BaseController ):
@web.expose
@web.require_login( "create/submit sequencing requests" )
- def list( self, trans, **kwargs ):
+ def list( self, trans, **kwd ):
'''
List all request made by the current user
'''
- status = message = None
- self.request_grid.default_filter = dict(state=trans.app.model.Request.states.UNSUBMITTED,
- deleted=False)
- if 'operation' in kwargs:
- operation = kwargs['operation'].lower()
+
+ if 'operation' in kwd:
+ operation = kwd['operation'].lower()
+ if not kwd.get( 'id', None ):
+ return trans.response.send_redirect( web.url_for( controller='requests',
+ action='list',
+ status='error',
+ message="Invalid request ID") )
if operation == "show_request":
- id = trans.security.decode_id(kwargs['id'])
- return self.__show_request(trans, id, kwargs.get('add_sample', False))
+ return self.__show_request( trans, **kwd )
elif operation == "submit":
- id = trans.security.decode_id(kwargs['id'])
- return self.__submit_request(trans, id)
+ return self.__submit_request( trans, **kwd )
elif operation == "delete":
- id = trans.security.decode_id(kwargs['id'])
- return self.__delete_request(trans, id)
+ return self.__delete_request( trans, **kwd )
elif operation == "undelete":
- id = trans.security.decode_id(kwargs['id'])
- return self.__undelete_request(trans, id)
+ return self.__undelete_request( trans, **kwd )
elif operation == "edit":
- id = trans.security.decode_id(kwargs['id'])
- return self.__edit_request(trans, id)
- if 'show_filter' in kwargs.keys():
- if kwargs['show_filter'] == 'All':
- self.request_grid.default_filter = {}
- elif kwargs['show_filter'] == 'Deleted':
- self.request_grid.default_filter = dict(deleted=True)
- else:
- self.request_grid.default_filter = dict(state=kwargs['show_filter'], deleted=False)
- self.request_grid.show_filter = kwargs.get('show_filter', trans.app.model.Request.states.UNSUBMITTED)
+ return self.__edit_request( trans, **kwd )
# Render the list view
- return self.request_grid( trans, **kwargs )
+ return self.request_grid( trans, **kwd )
- def __show_request(self, trans, id, add_sample=False):
+ def __show_request(self, trans, **kwd):
+ params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ add_sample = params.get('add_sample', False)
try:
- request = trans.sa_session.query( trans.app.model.Request ).get( id )
+ request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id(kwd['id']) )
except:
return trans.response.send_redirect( web.url_for( controller='requests',
action='list',
status='error',
- message="Invalid request ID",
- **kwd) )
+ message="Invalid request ID" ) )
current_samples = []
for s in request.samples:
current_samples.append([s.name, s.values.content])
@@ -122,10 +167,11 @@ class Requests( BaseController ):
current_samples.append(['Sample_%i' % (len(current_samples)+1),['' for field in request.type.sample_form.fields]])
return trans.fill_template( '/requests/show_request.mako',
request=request,
- request_details=self.request_details(trans, id),
+ request_details=self.request_details(trans, request.id),
current_samples = current_samples,
sample_copy=self.__copy_sample(current_samples),
- details='hide', edit_mode='False')
+ details='hide', edit_mode='False',
+ msg=msg, messagetype=messagetype )
def request_details(self, trans, id):
'''
Shows the request details
@@ -685,7 +731,7 @@ class Requests( BaseController ):
message="Invalid request ID",
**kwd) )
if params.get('show', False) == 'True':
- return self.__edit_request(trans, request.id, **kwd)
+ return self.__edit_request(trans, **kwd)
elif params.get('save_changes_request_button', False) == 'Save changes' \
or params.get('edit_samples_button', False) == 'Edit samples':
request_type = trans.sa_session.query( trans.app.model.RequestType ).get( int( params.select_request_type ) )
@@ -714,11 +760,11 @@ class Requests( BaseController ):
messagetype='done',
**new_kwd) )
elif params.get('refresh', False) == 'true':
- return self.__edit_request(trans, request.id, **kwd)
+ return self.__edit_request(trans, **kwd)
- def __edit_request(self, trans, id, **kwd):
+ def __edit_request(self, trans, **kwd):
try:
- request = trans.sa_session.query( trans.app.model.Request ).get( id )
+ request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id(kwd['id']) )
except:
msg = "Invalid request ID"
log.warn( msg )
@@ -758,59 +804,61 @@ class Requests( BaseController ):
msg=msg,
messagetype=messagetype)
return self.__show_request_form(trans)
- def __delete_request(self, trans, id):
- try:
- request = trans.sa_session.query( trans.app.model.Request ).get( id )
- except:
- msg = "Invalid request ID"
- log.warn( msg )
- return trans.response.send_redirect( web.url_for( controller='requests',
- action='list',
- status='error',
- message=msg,
- **kwd) )
- # change request's submitted field
- if not request.unsubmitted():
- return trans.response.send_redirect( web.url_for( controller='requests',
- action='list',
- status='error',
- message='This request cannot be deleted as it is already been submitted',
- **kwd) )
- request.deleted = True
- trans.sa_session.add( request )
- trans.sa_session.flush()
- kwd = {}
- kwd['id'] = trans.security.encode_id(request.id)
+ def __delete_request(self, trans, **kwd):
+ id_list = util.listify( kwd['id'] )
+ delete_failed = []
+ for id in id_list:
+ try:
+ request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id(id) )
+ except:
+ msg = "Invalid request ID"
+ log.warn( msg )
+ return trans.response.send_redirect( web.url_for( controller='requests',
+ action='list',
+ status='error',
+ message=msg,
+ **kwd) )
+ # a request cannot be deleted once its submitted
+ if not request.unsubmitted():
+ delete_failed.append(request.name)
+ else:
+ request.deleted = True
+ trans.sa_session.add( request )
+ trans.sa_session.flush()
+ if not len(delete_failed):
+ msg = '%i request(s) has been deleted.' % len(id_list)
+ status = 'done'
+ else:
+ msg = '%i request(s) has been deleted. %i request %s could not be deleted as they have been submitted.' % (len(id_list)-len(delete_failed),
+ len(delete_failed), str(delete_failed))
+ status = 'warning'
+ return trans.response.send_redirect( web.url_for( controller='requests',
+ action='list',
+ status=status,
+ message=msg) )
+ def __undelete_request(self, trans, **kwd):
+ id_list = util.listify( kwd['id'] )
+ for id in id_list:
+ try:
+ request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id(id) )
+ except:
+ msg = "Invalid request ID"
+ log.warn( msg )
+ return trans.response.send_redirect( web.url_for( controller='requests',
+ action='list',
+ status='error',
+ message=msg,
+ **kwd) )
+ request.deleted = False
+ trans.sa_session.add( request )
+ trans.sa_session.flush()
return trans.response.send_redirect( web.url_for( controller='requests',
action='list',
status='done',
- message='The request %s has been deleted.' % request.name,
- **kwd) )
- def __undelete_request(self, trans, id):
+ message='%i request(s) has been undeleted.' % len(id_list) ) )
+ def __submit_request(self, trans, **kwd):
try:
- request = trans.sa_session.query( trans.app.model.Request ).get( id )
- except:
- msg = "Invalid request ID"
- log.warn( msg )
- return trans.response.send_redirect( web.url_for( controller='requests',
- action='list',
- status='error',
- message=msg,
- **kwd) )
- # change request's submitted field
- request.deleted = False
- trans.sa_session.add( request )
- trans.sa_session.flush()
- kwd = {}
- kwd['id'] = trans.security.encode_id(request.id)
- return trans.response.send_redirect( web.url_for( controller='requests',
- action='list',
- status='done',
- message='The request %s has been undeleted.' % request.name,
- **kwd) )
- def __submit_request(self, trans, id):
- try:
- request = trans.sa_session.query( trans.app.model.Request ).get( id )
+ request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id(kwd['id']) )
except:
msg = "Invalid request ID"
log.warn( msg )
@@ -837,14 +885,12 @@ class Requests( BaseController ):
request.state = request.states.SUBMITTED
trans.sa_session.add( request )
trans.sa_session.flush()
- kwd = {}
- kwd['id'] = trans.security.encode_id(request.id)
- kwd['status'] = 'done'
- kwd['message'] = 'The request %s has been submitted.' % request.name
return trans.response.send_redirect( web.url_for( controller='requests',
action='list',
- show_filter=trans.app.model.Request.states.SUBMITTED,
- **kwd) )
+ id=trans.security.encode_id(request.id),
+ status='done',
+ message='The request %s has been submitted.' % request.name
+ ) )
@web.expose
@web.require_login( "create/submit sequencing requests" )
def show_events(self, trans, **kwd):
diff --git a/lib/galaxy/web/controllers/requests_admin.py b/lib/galaxy/web/controllers/requests_admin.py
index a58f7fe84d7..a11ca5f0e85 100644
--- a/lib/galaxy/web/controllers/requests_admin.py
+++ b/lib/galaxy/web/controllers/requests_admin.py
@@ -15,63 +15,187 @@ log = logging.getLogger( __name__ )
# ---- Request Grid ------------------------------------------------------------
#
-class RequestsListGrid( grids.Grid ):
+class RequestsGrid( grids.Grid ):
+ # Custom column types
+ class NameColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, request):
+ return request.name
+ class DescriptionColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, request):
+ return request.desc
+ class SamplesColumn( grids.GridColumn ):
+ def get_value(self, trans, grid, request):
+ return str(len(request.samples))
+ class TypeColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, request):
+ return request.type.name
+ class LastUpdateColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, request):
+ return request.update_time
+ class StateColumn( grids.GridColumn ):
+ def filter( self, db_session, query, column_filter ):
+ """ Modify query to filter request by state. """
+ if column_filter == "All":
+ return query
+ if column_filter:
+ query = query.filter( model.Request.state == column_filter )
+ return query
+ def get_accepted_filters( self ):
+ """ Returns a list of accepted filters for this column. """
+ accepted_filter_labels_and_vals = [ model.Request.states.UNSUBMITTED,
+ model.Request.states.SUBMITTED,
+ model.Request.states.COMPLETE,
+ "All"]
+ accepted_filters = []
+ for val in accepted_filter_labels_and_vals:
+ label = val.lower()
+ args = { self.key: val }
+ accepted_filters.append( grids.GridColumnFilter( label, args) )
+ return accepted_filters
+ class UserColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, request):
+ return request.user.email
+ class DeletedColumn( grids.GridColumn ):
+ def get_accepted_filters( self ):
+ """ Returns a list of accepted filters for this column. """
+ accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" }
+ accepted_filters = []
+ for label, val in accepted_filter_labels_and_vals.items():
+ args = { self.key: val }
+ accepted_filters.append( grids.GridColumnFilter( label, args) )
+ return accepted_filters
+ # Grid definition
title = "Sequencing Requests"
template = "admin/requests/grid.mako"
model_class = model.Request
default_sort_key = "-create_time"
- show_filter = model.Request.states.SUBMITTED
+ num_rows_per_page = 50
+ preserve_state = True
+ use_paging = True
+ default_filter = dict( deleted="False", state=model.Request.states.SUBMITTED)
columns = [
- grids.GridColumn( "Name", key="name",
- link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ),
- attach_popup=True ),
- grids.GridColumn( "Description", key="desc"),
- grids.GridColumn( "Sample(s)", method='number_of_samples',
- link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ), ),
- grids.GridColumn( "Type", key="request_type_id", method='get_request_type'),
- grids.GridColumn( "Last update", key="update_time", format=time_ago ),
- grids.GridColumn( "State", key='state'),
- grids.GridColumn( "User", key="user_id", method='get_user')
-
+ NameColumn( "Name",
+ key="name",
+ model_class=model.Request,
+ link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ),
+ attach_popup=True,
+ filterable="advanced" ),
+ DescriptionColumn( "Description",
+ key='desc',
+ model_class=model.Request,
+ filterable="advanced" ),
+ SamplesColumn( "Sample(s)",
+ link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ), ),
+ TypeColumn( "Type" ),
+ LastUpdateColumn( "Last update",
+ format=time_ago ),
+ StateColumn( "State",
+ key='state',
+ filterable="advanced"),
+ UserColumn( "User",
+ key='user.email',
+ model_class=model.Request,
+ filterable="advanced" ),
+ DeletedColumn( "Deleted",
+ key="deleted",
+ visible=True,
+ filterable="advanced" )
]
+ columns.append( grids.MulticolFilterColumn( "Search",
+ cols_to_filter=[ columns[0], columns[1], columns[6] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
operations = [
grids.GridOperation( "Submit", allow_multiple=False, condition=( lambda item: not item.deleted and item.unsubmitted() and item.samples ) ),
grids.GridOperation( "Edit", allow_multiple=False, condition=( lambda item: not item.deleted ) ),
grids.GridOperation( "Reject", allow_multiple=False, condition=( lambda item: not item.deleted and item.submitted() ) ),
- grids.GridOperation( "Delete", allow_multiple=False, condition=( lambda item: not item.deleted and item.unsubmitted() ) ),
+ grids.GridOperation( "Delete", allow_multiple=True, condition=( lambda item: not item.deleted and item.unsubmitted() ) ),
grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ) ),
]
- standard_filters = [
- grids.GridColumnFilter( model.Request.states.UNSUBMITTED,
- args=dict( state=model.Request.states.UNSUBMITTED, deleted=False ) ),
- grids.GridColumnFilter( model.Request.states.SUBMITTED,
- args=dict( state=model.Request.states.SUBMITTED, deleted=False ) ),
- grids.GridColumnFilter( model.Request.states.COMPLETE, args=dict( state=model.Request.states.COMPLETE, deleted=False ) ),
- grids.GridColumnFilter( "Deleted", args=dict( deleted=True ) ),
- grids.GridColumnFilter( "All", args=dict( deleted=False ) )
+ global_actions = [
+ grids.GridAction( "Create new request", dict( controller='requests_admin',
+ action='new',
+ select_request_type='True' ) )
]
- def get_user(self, trans, request):
- return trans.sa_session.query( trans.app.model.User ).get( request.user_id ).email
- def get_current_item( self, trans ):
- return None
- def get_request_type(self, trans, request):
- request_type = trans.sa_session.query( trans.app.model.RequestType ).get( request.request_type_id )
- return request_type.name
- def number_of_samples(self, trans, request):
- return str(len(request.samples))
- def apply_default_filter( self, trans, query, **kwargs ):
- if self.default_filter:
- return query.filter_by( **self.default_filter )
- else:
- return query
-
+
+#
+# ---- Request Type Gridr ------------------------------------------------------
+#
+class RequestTypeGrid( grids.Grid ):
+ # Custom column types
+ class NameColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, request_type):
+ return request_type.name
+ class DescriptionColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, request_type):
+ return request_type.desc
+ class RequestFormColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, request_type):
+ return request_type.request_form.name
+ class SampleFormColumn( grids.TextColumn ):
+ def get_value(self, trans, grid, request_type):
+ return request_type.sample_form.name
+ class DeletedColumn( grids.GridColumn ):
+ def get_accepted_filters( self ):
+ """ Returns a list of accepted filters for this column. """
+ accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" }
+ accepted_filters = []
+ for label, val in accepted_filter_labels_and_vals.items():
+ args = { self.key: val }
+ accepted_filters.append( grids.GridColumnFilter( label, args) )
+ return accepted_filters
+ # Grid definition
+ title = "Requests Types"
+ template = "admin/requests/manage_request_types.mako"
+ model_class = model.RequestType
+ default_sort_key = "-create_time"
+ num_rows_per_page = 50
+ preserve_state = True
+ use_paging = True
+ default_filter = dict( deleted="False" )
+ columns = [
+ NameColumn( "Name",
+ key="name",
+ model_class=model.RequestType,
+ link=( lambda item: iff( item.deleted, None, dict( operation="view", id=item.id ) ) ),
+ attach_popup=True,
+ filterable="advanced" ),
+ DescriptionColumn( "Description",
+ key='desc',
+ model_class=model.Request,
+ filterable="advanced" ),
+ RequestFormColumn( "Request Form",
+ link=( lambda item: iff( item.deleted, None, dict( operation="view_form", id=item.request_form.id ) ) ), ),
+ SampleFormColumn( "Sample Form",
+ link=( lambda item: iff( item.deleted, None, dict( operation="view_form", id=item.sample_form.id ) ) ), ),
+ DeletedColumn( "Deleted",
+ key="deleted",
+ visible=False,
+ filterable="advanced" )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+ operations = [
+ #grids.GridOperation( "Update", allow_multiple=False, condition=( lambda item: not item.deleted ) ),
+ grids.GridOperation( "Delete", allow_multiple=True, condition=( lambda item: not item.deleted ) ),
+ grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ) ),
+ ]
+ global_actions = [
+ grids.GridAction( "Create new request type", dict( controller='requests_admin',
+ action='create_request_type' ) )
+ ]
#
# ---- Request Controller ------------------------------------------------------
#
class Requests( BaseController ):
- request_grid = RequestsListGrid()
+ request_grid = RequestsGrid()
+ requesttype_grid = RequestTypeGrid()
@web.expose
@web.require_admin
@@ -80,67 +204,59 @@ class Requests( BaseController ):
@web.expose
@web.require_admin
- def list( self, trans, **kwargs ):
+ def list( self, trans, **kwd ):
'''
List all request made by the current user
'''
- message = util.restore_text( kwargs.get( 'message', '' ) )
- status = kwargs.get( 'status', 'done' )
- self.request_grid.default_filter = dict(state=trans.app.model.Request.states.SUBMITTED,
- deleted=False)
- if 'operation' in kwargs:
- operation = kwargs['operation'].lower()
+ if 'operation' in kwd:
+ operation = kwd['operation'].lower()
+ if not kwd.get( 'id', None ):
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message="Invalid request ID") )
if operation == "show_request":
- id = trans.security.decode_id(kwargs['id'])
- return self.__show_request(trans, id, status, message)
+ return self.__show_request( trans, **kwd )
elif operation == "submit":
- id = trans.security.decode_id(kwargs['id'])
- return self.__submit_request(trans, id)
- elif operation == "edit":
- id = trans.security.decode_id(kwargs['id'])
- return self.__edit_request(trans, id)
+ return self.__submit_request( trans, **kwd )
elif operation == "delete":
- id = trans.security.decode_id(kwargs['id'])
- return self.__delete_request(trans, id)
+ return self.__delete_request( trans, **kwd )
elif operation == "undelete":
- id = trans.security.decode_id(kwargs['id'])
- return self.__undelete_request(trans, id)
+ return self.__undelete_request( trans, **kwd )
+ elif operation == "edit":
+ return self.__edit_request( trans, **kwd )
elif operation == "reject":
- id = trans.security.decode_id(kwargs['id'])
- return self.__reject_request(trans, id)
- if 'show_filter' in kwargs.keys():
- if kwargs['show_filter'] == 'All':
- self.request_grid.default_filter = {}
- elif kwargs['show_filter'] == 'Deleted':
- self.request_grid.default_filter = dict(deleted=True)
- else:
- self.request_grid.default_filter = dict(state=kwargs['show_filter'], deleted=False)
- self.request_grid.show_filter = kwargs.get('show_filter', trans.app.model.Request.states.SUBMITTED)
- # Render the list view
- return self.request_grid( trans, **kwargs )
- def __show_request(self, trans, id, messagetype, msg):
+ return self.__reject_request( trans, **kwd )
+ # Render the grid view
+ return self.request_grid( trans, **kwd )
+ def __show_request(self, trans, **kwd):
+ params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ add_sample = params.get('add_sample', False)
try:
- request = trans.sa_session.query( trans.app.model.Request ).get( id )
+ request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id(kwd['id']) )
except:
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='list',
status='error',
- message="Invalid request ID",
- **kwd) )
+ message="Invalid request ID") )
current_samples = []
for s in request.samples:
current_samples.append([s.name, s.values.content])
+ if add_sample:
+ current_samples.append(['Sample_%i' % (len(current_samples)+1),['' for field in request.type.sample_form.fields]])
return trans.fill_template( '/admin/requests/show_request.mako',
request=request,
- request_details=self.request_details(trans, id),
+ request_details=self.request_details(trans, request.id),
current_samples = current_samples,
sample_copy=self.__copy_sample(current_samples),
details='hide', edit_mode='False',
- msg=msg, messagetype=messagetype)
+ msg=msg, messagetype=messagetype )
- def __edit_request(self, trans, id, **kwd):
+ def __edit_request(self, trans, **kwd):
try:
- request = trans.sa_session.query( trans.app.model.Request ).get( id )
+ request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id(kwd['id']) )
except:
msg = "Invalid request ID"
log.warn( msg )
@@ -180,61 +296,61 @@ class Requests( BaseController ):
msg=msg,
messagetype=messagetype)
return self.__show_request_form(trans)
- def __delete_request(self, trans, id):
- try:
- request = trans.sa_session.query( trans.app.model.Request ).get( id )
- except:
- msg = "Invalid request ID"
- log.warn( msg )
- return trans.response.send_redirect( web.url_for( controller='requests_admin',
- action='list',
- status='error',
- message=msg,
- **kwd) )
- # change request's submitted field
- if not request.unsubmitted():
- return trans.response.send_redirect( web.url_for( controller='requests_admin',
- action='list',
- status='error',
- message='This request cannot be deleted as it is already been submitted',
- **kwd) )
- request.deleted = True
- trans.sa_session.add( request )
- trans.sa_session.flush()
- kwd = {}
- kwd['id'] = trans.security.encode_id(request.id)
+ def __delete_request(self, trans, **kwd):
+ id_list = util.listify( kwd['id'] )
+ delete_failed = []
+ for id in id_list:
+ try:
+ request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id(id) )
+ except:
+ msg = "Invalid request ID"
+ log.warn( msg )
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message=msg,
+ **kwd) )
+ # a request cannot be deleted once its submitted
+ if not request.unsubmitted():
+ delete_failed.append(request.name)
+ else:
+ request.deleted = True
+ trans.sa_session.add( request )
+ trans.sa_session.flush()
+ if not len(delete_failed):
+ msg = '%i request(s) has been deleted.' % len(id_list)
+ status = 'done'
+ else:
+ msg = '%i request(s) has been deleted. %i request %s could not be deleted as they have been submitted.' % (len(id_list)-len(delete_failed),
+ len(delete_failed), str(delete_failed))
+ status = 'warning'
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='list',
- show_filter=trans.app.model.Request.states.UNSUBMITTED,
- status='done',
- message='The request %s has been deleted.' % request.name,
- **kwd) )
- def __undelete_request(self, trans, id):
- try:
- request = trans.sa_session.query( trans.app.model.Request ).get( id )
- except:
- msg = "Invalid request ID"
- log.warn( msg )
- return trans.response.send_redirect( web.url_for( controller='requests_admin',
- action='list',
- status='error',
- message=msg,
- **kwd) )
- # change request's submitted field
- request.deleted = False
- trans.sa_session.add( request )
- trans.sa_session.flush()
- kwd = {}
- kwd['id'] = trans.security.encode_id(request.id)
+ status=status,
+ message=msg) )
+ def __undelete_request(self, trans, **kwd):
+ id_list = util.listify( kwd['id'] )
+ for id in id_list:
+ try:
+ request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id(id) )
+ except:
+ msg = "Invalid request ID"
+ log.warn( msg )
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message=msg,
+ **kwd) )
+ request.deleted = False
+ trans.sa_session.add( request )
+ trans.sa_session.flush()
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='list',
- show_filter=trans.app.model.Request.states.UNSUBMITTED,
status='done',
- message='The request %s has been undeleted.' % request.name,
- **kwd) )
- def __submit_request(self, trans, id):
+ message='%i request(s) has been undeleted.' % len(id_list) ) )
+ def __submit_request(self, trans, **kwd):
try:
- request = trans.sa_session.query( trans.app.model.Request ).get( id )
+ request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id(kwd['id']) )
except:
msg = "Invalid request ID"
log.warn( msg )
@@ -260,15 +376,32 @@ class Requests( BaseController ):
request.state = request.states.SUBMITTED
trans.sa_session.add( request )
trans.sa_session.flush()
- kwd = {}
- kwd['id'] = trans.security.encode_id(request.id)
- kwd['status'] = 'done'
- kwd['message'] = 'The request %s has been submitted.' % request.name
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='list',
- show_filter=trans.app.model.Request.states.SUBMITTED,
- **kwd) )
-
+ id=trans.security.encode_id(request.id),
+ status='done',
+ message='The request %s has been submitted.' % request.name
+ ) )
+ def __reject_request(self, trans, **kwd):
+ try:
+ request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id(kwd['id']) )
+ except:
+ msg = "Invalid request ID"
+ log.warn( msg )
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message=msg,
+ **kwd) )
+ # change request's submitted field
+ request.state = request.states.UNSUBMITTED
+ trans.sa_session.add( request )
+ trans.sa_session.flush()
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='done',
+ message='The request %s is now unsubmitted.' % request.name
+ ) )
#
#---- Request Creation ----------------------------------------------------------
#
@@ -325,7 +458,6 @@ class Requests( BaseController ):
if params.get('create_request_button', False) == 'Save':
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='list',
- show_filter=trans.app.model.Request.states.UNSUBMITTED,
message=msg ,
status='done') )
elif params.get('create_request_samples_button', False) == 'Add samples':
@@ -664,29 +796,6 @@ class Requests( BaseController ):
**new_kwd) )
elif params.get('refresh', False) == 'true':
return self.__edit_request(trans, request.id, **kwd)
- def __reject_request(self, trans, id):
- try:
- request = trans.sa_session.query( trans.app.model.Request ).get( id )
- except:
- msg = "Invalid request ID"
- log.warn( msg )
- return trans.response.send_redirect( web.url_for( controller='requests_admin',
- action='list',
- status='error',
- message=msg,
- **kwd) )
- # change request's submitted field
- request.state = request.states.UNSUBMITTED
- trans.sa_session.add( request )
- trans.sa_session.flush()
- kwd = {}
- kwd['id'] = trans.security.encode_id(request.id)
- kwd['status'] = 'done'
- kwd['message'] = 'The request %s is now unsubmitted.' % request.name
- return trans.response.send_redirect( web.url_for( controller='requests_admin',
- action='list',
- show_filter=trans.app.model.Request.states.UNSUBMITTED,
- **kwd) )
def __update_samples(self, request, **kwd):
'''
This method retrieves all the user entered sample information and
@@ -1049,8 +1158,8 @@ class Requests( BaseController ):
action='list',
operation='show_request',
id=trans.security.encode_id(request.id),
- message='Bar codes have been saved for this request',
- status='done'))
+ msg='Bar codes have been saved for this request',
+ messagetype='done'))
def __set_request_state( self, trans, request ):
# check if all the samples of the current request are in the final state
complete = True
@@ -1138,50 +1247,72 @@ class Requests( BaseController ):
##
@web.expose
@web.require_admin
- def manage_request_types( self, trans, **kwd ):
- params = util.Params( kwd )
- msg = util.restore_text( params.get( 'msg', '' ) )
- messagetype = params.get( 'messagetype', 'done' )
- show_filter = util.restore_text( params.get( 'show_filter', 'Active' ) )
- forms = get_all_forms(trans, all_versions=True)
- request_types_list = trans.sa_session.query( trans.app.model.RequestType )
- if show_filter == 'All':
- request_types = request_types_list
- elif show_filter == 'Deleted':
- request_types = [rt for rt in request_types_list if rt.deleted]
- else:
- request_types = [rt for rt in request_types_list if not rt.deleted]
- return trans.fill_template( '/admin/requests/manage_request_types.mako',
- request_types=request_types,
- forms=forms,
- show_filter=show_filter,
- msg=msg,
- messagetype=messagetype )
+ def manage_request_types( self, trans, **kwd ):
+ if 'operation' in kwd:
+ operation = kwd['operation'].lower()
+ if not kwd.get( 'id', None ):
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='manage_request_types',
+ status='error',
+ message="Invalid requesttype ID") )
+ if operation == "view":
+ return self.__view_request_type( trans, **kwd )
+ elif operation == "view_form":
+ return self.__view_form( trans, **kwd )
+ elif operation == "delete":
+ return self.__delete_request_type( trans, **kwd )
+ elif operation == "undelete":
+ return self.__undelete_request_type( trans, **kwd )
+# elif operation == "update":
+# return self.__edit_request( trans, **kwd )
+ # Render the grid view
+ return self.requesttype_grid( trans, **kwd )
+ def __view_request_type(self, trans, **kwd):
+ try:
+ rt = trans.sa_session.query( trans.app.model.RequestType ).get( trans.security.decode_id(kwd['id']) )
+ except:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='manage_request_types',
+ status='error',
+ message="Invalid requesttype ID") )
+ return trans.fill_template( '/admin/requests/view_request_type.mako',
+ request_type=rt,
+ forms=get_all_forms( trans ),
+ states_list=rt.states )
+ def __view_form(self, trans, **kwd):
+ try:
+ fd = trans.sa_session.query( trans.app.model.FormDefinition ).get( trans.security.decode_id(kwd['id']) )
+ except:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='manage_request_types',
+ status='error',
+ message="Invalid form ID") )
+ return trans.fill_template( '/admin/forms/show_form_read_only.mako',
+ form=fd )
+
@web.expose
@web.require_admin
- def request_type( self, trans, **kwd ):
+ def create_request_type( self, trans, **kwd ):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
- if params.get( 'create', False ):
+ if params.get( 'add_state_button', False ):
+ rt_info, rt_states = self.__create_request_type_form(trans, **kwd)
+ rt_states.append(("", ""))
return trans.fill_template( '/admin/requests/create_request_type.mako',
- request_forms=get_all_forms( trans,
- filter=dict(deleted=False),
- form_type=trans.app.model.FormDefinition.types.REQUEST ),
- sample_forms=get_all_forms( trans,
- filter=dict(deleted=False),
- form_type=trans.app.model.FormDefinition.types.SAMPLE ),
+ rt_info_widgets=rt_info,
+ rt_states_widgets=rt_states,
msg=msg,
messagetype=messagetype)
- elif params.get( 'define_states_button', False ):
- return trans.fill_template( '/admin/requests/add_states.mako',
- request_type_name=util.restore_text( params.name ),
- desc=util.restore_text( params.description ),
- num_states=int(util.restore_text( params.num_states )),
- request_form_id=int(util.restore_text( params.request_form_id )),
- sample_form_id=int(util.restore_text( params.sample_form_id )),
+ elif params.get( 'remove_state_button', False ):
+ rt_info, rt_states = self.__create_request_type_form(trans, **kwd)
+ index = int(params.get( 'remove_state_button', '' ).split(" ")[2])
+ del rt_states[index-1]
+ return trans.fill_template( '/admin/requests/create_request_type.mako',
+ rt_info_widgets=rt_info,
+ rt_states_widgets=rt_states,
msg=msg,
- messagetype=messagetype)
+ messagetype=messagetype)
elif params.get( 'save_request_type', False ):
st, msg = self.__save_request_type(trans, **kwd)
if not st:
@@ -1191,32 +1322,65 @@ class Requests( BaseController ):
messagetype='error')
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='manage_request_types',
- msg='Request type %s has been created' % st.name,
- messagetype='done') )
- elif params.get('view', False):
- rt = trans.sa_session.query( trans.app.model.RequestType ).get( int( util.restore_text( params.id ) ) )
- return trans.fill_template( '/admin/requests/view_request_type.mako',
- request_type=rt,
- forms=get_all_forms( trans ),
- states_list=rt.states,
- deleted=False,
- show_deleted=False,
+ message='Request type %s has been created' % st.name,
+ status='done') )
+ else:
+ rt_info, rt_states = self.__create_request_type_form(trans, **kwd)
+ return trans.fill_template( '/admin/requests/create_request_type.mako',
+ rt_info_widgets=rt_info,
+ rt_states_widgets=rt_states,
msg=msg,
- messagetype=messagetype )
+ messagetype=messagetype)
+ def __create_request_type_form(self, trans, **kwd):
+ request_forms=get_all_forms( trans,
+ filter=dict(deleted=False),
+ form_type=trans.app.model.FormDefinition.types.REQUEST )
+ sample_forms=get_all_forms( trans,
+ filter=dict(deleted=False),
+ form_type=trans.app.model.FormDefinition.types.SAMPLE )
+ if not len(request_forms) or not len(sample_forms):
+ return [],[]
+ params = util.Params( kwd )
+ rt_info = []
+ rt_info.append(dict(label='Name',
+ widget=TextField('name', 40, util.restore_text( params.get( 'name', '' ) ) ) ))
+ rt_info.append(dict(label='Description',
+ widget=TextField('desc', 40, util.restore_text( params.get( 'desc', '' ) ) ) ))
+
+ rf_selectbox = SelectField('request_form_id')
+ for fd in request_forms:
+ if str(fd.id) == params.get( 'request_form_id', '' ):
+ rf_selectbox.add_option(fd.name, fd.id, selected=True)
+ else:
+ rf_selectbox.add_option(fd.name, fd.id)
+ rt_info.append(dict(label='Request form',
+ widget=rf_selectbox ))
+
+ sf_selectbox = SelectField('sample_form_id')
+ for fd in sample_forms:
+ if str(fd.id) == params.get( 'sample_form_id', '' ):
+ sf_selectbox.add_option(fd.name, fd.id, selected=True)
+ else:
+ sf_selectbox.add_option(fd.name, fd.id)
+ rt_info.append(dict(label='Sample form',
+ widget=sf_selectbox ))
+ # possible sample states
+ rt_states = []
+ i=0
+ while True:
+ if kwd.has_key( 'state_name_%i' % i ):
+ rt_states.append((params.get( 'state_name_%i' % i, '' ),
+ params.get( 'state_desc_%i' % i, '' )))
+ i=i+1
+ else:
+ break
+ return rt_info, rt_states
+
def __save_request_type(self, trans, **kwd):
params = util.Params( kwd )
- num_states = int( util.restore_text( params.get( 'num_states', 0 ) ))
- proceed = True
- for i in range( num_states ):
- if not util.restore_text( params.get( 'state_name_%i' % i, None ) ):
- proceed = False
- break
- if not proceed:
- msg = "All the state name(s) must be completed."
- return None, msg
rt = trans.app.model.RequestType()
- rt.name = util.restore_text( params.name )
- rt.desc = util.restore_text( params.description ) or ""
+ rt.name = util.restore_text( params.get( 'name', '' ) )
+ rt.desc = util.restore_text( params.get( 'desc', '' ) )
rt.request_form = trans.sa_session.query( trans.app.model.FormDefinition ).get( int( params.request_form_id ) )
rt.sample_form = trans.sa_session.query( trans.app.model.FormDefinition ).get( int( params.sample_form_id ) )
trans.sa_session.add( rt )
@@ -1226,37 +1390,50 @@ class Requests( BaseController ):
for ss in ss_list:
trans.sa_session.delete( ss )
trans.sa_session.flush()
- for i in range( num_states ):
- name = util.restore_text( params.get( 'state_name_%i' % i, None ))
- desc = util.restore_text( params.get( 'state_desc_%i' % i, None ))
- ss = trans.app.model.SampleState(name, desc, rt)
- trans.sa_session.add( ss )
- trans.sa_session.flush()
- msg = "The new request type named '%s' with %s state(s) has been created" % (rt.name, num_states)
+ i=0
+ while True:
+ if kwd.has_key( 'state_name_%i' % i ):
+ name = util.restore_text( params.get( 'state_name_%i' % i, None ))
+ desc = util.restore_text( params.get( 'state_desc_%i' % i, None ))
+ ss = trans.app.model.SampleState(name, desc, rt)
+ trans.sa_session.add( ss )
+ trans.sa_session.flush()
+ i = i + 1
+ else:
+ break
+ msg = "The new request type named '%s' with %s state(s) has been created" % (rt.name, i)
return rt, msg
- @web.expose
- @web.require_admin
- def delete_request_type( self, trans, **kwd ):
- params = util.Params( kwd )
- msg = util.restore_text( params.get( 'msg', '' ) )
- messagetype = params.get( 'messagetype', 'done' )
- rt = trans.sa_session.query( trans.app.model.RequestType ).get( int( util.restore_text( params.request_type_id ) ) )
- rt.deleted = True
- trans.sa_session.flush()
+ def __delete_request_type( self, trans, **kwd ):
+ id_list = util.listify( kwd['id'] )
+ for id in id_list:
+ try:
+ rt = trans.sa_session.query( trans.app.model.RequestType ).get( trans.security.decode_id(id) )
+ except:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='manage_request_types',
+ msg='Invalid request type ID',
+ messagetype='error') )
+ rt.deleted = True
+ trans.sa_session.add( rt )
+ trans.sa_session.flush()
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='manage_request_types',
- msg='Request type %s has been deleted' % rt.name,
+ msg='%i request type(s) has been deleted' % len(id_list),
messagetype='done') )
- @web.expose
- @web.require_admin
- def undelete_request_type( self, trans, **kwd ):
- params = util.Params( kwd )
- msg = util.restore_text( params.get( 'msg', '' ) )
- messagetype = params.get( 'messagetype', 'done' )
- rt = trans.sa_session.query( trans.app.model.RequestType ).get( int( util.restore_text( params.request_type_id ) ) )
- rt.deleted = False
- trans.sa_session.flush()
+ def __undelete_request_type( self, trans, **kwd ):
+ id_list = util.listify( kwd['id'] )
+ for id in id_list:
+ try:
+ rt = trans.sa_session.query( trans.app.model.RequestType ).get( trans.security.decode_id(id) )
+ except:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='manage_request_types',
+ msg='Invalid request type ID',
+ messagetype='error') )
+ rt.deleted = False
+ trans.sa_session.add( rt )
+ trans.sa_session.flush()
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='manage_request_types',
- msg='Request type %s has been undeleted' % rt.name,
+ msg='%i request type(s) has been undeleted' % len(id_list),
messagetype='done') )
diff --git a/lib/galaxy/web/controllers/user.py b/lib/galaxy/web/controllers/user.py
index a017ff97143..f056d3a584c 100644
--- a/lib/galaxy/web/controllers/user.py
+++ b/lib/galaxy/web/controllers/user.py
@@ -181,9 +181,7 @@ class User( BaseController ):
refresh_frames = [ 'masthead', 'history' ]
if not trans.app.config.allow_user_creation and not trans.user_is_admin():
return trans.show_error_message( 'User registration is disabled. Please contact your Galaxy administrator for an account.' )
- #
# Create the user, save all the user info and login to Galaxy
- #
if params.get('create_user_button', None) == "Submit":
# check email and password validity
error = self.__validate(trans, params, email, password, confirm)
diff --git a/lib/galaxy/web/framework/__init__.py b/lib/galaxy/web/framework/__init__.py
index 81fe01c5bf6..5efec6a0bdc 100644
--- a/lib/galaxy/web/framework/__init__.py
+++ b/lib/galaxy/web/framework/__init__.py
@@ -446,13 +446,11 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
self.sa_session.flush()
# This method is not called from the Galaxy reports, so the cookie will always be galaxysession
self.__update_session_cookie( name='galaxysession' )
-
def get_galaxy_session( self ):
"""
Return the current galaxy session
"""
return self.galaxy_session
-
def get_history( self, create=False ):
"""
Load the current history, creating a new one only if there is not
@@ -497,7 +495,6 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
self.sa_session.add_all( ( self.galaxy_session, history ) )
self.sa_session.flush()
return history
-
def get_user( self ):
"""Return the current user if logged in or None."""
return self.galaxy_session.user
@@ -507,7 +504,6 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
self.sa_session.add( self.galaxy_session )
self.sa_session.flush()
user = property( get_user, set_user )
-
def get_user_and_roles( self ):
user = self.get_user()
if user:
@@ -515,13 +511,9 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
else:
roles = []
return user, roles
-
def user_is_admin( self ):
admin_users = self.app.config.get( "admin_users", "" ).split( "," )
- if self.user and admin_users and self.user.email in admin_users:
- return True
- return False
-
+ return self.user and admin_users and self.user.email in admin_users
def get_toolbox(self):
"""Returns the application toolbox"""
return self.app.toolbox
diff --git a/lib/galaxy/web/framework/helpers/grids.py b/lib/galaxy/web/framework/helpers/grids.py
index 803e6bf5f15..16af3ff17ff 100644
--- a/lib/galaxy/web/framework/helpers/grids.py
+++ b/lib/galaxy/web/framework/helpers/grids.py
@@ -1,6 +1,7 @@
from galaxy.model import *
from galaxy.model.orm import *
+from galaxy.web.framework.helpers import iff
from galaxy.tags.tag_handler import TagHandler
from galaxy.web import url_for
from galaxy.util.json import from_json_string, to_json_string
@@ -16,7 +17,9 @@ class Grid( object ):
title = ""
exposed = True
model_class = None
+ # To use grid's async features, set template="grid_base_async.mako"
template = "grid_base.mako"
+ async_template = "grid_body_async.mako"
global_actions = []
columns = []
operations = []
@@ -213,7 +216,7 @@ class Grid( object ):
return url_for( **new_kwargs )
- return trans.fill_template( self.template,
+ return trans.fill_template( iff( 'async' not in kwargs, self.template, self.async_template),
grid=self,
query=query,
cur_page_num = page_num,
@@ -390,7 +393,7 @@ class MulticolFilterColumn( TextColumn ):
return query.filter( complete_filter )
class GridOperation( object ):
- def __init__( self, label, key=None, condition=None, allow_multiple=True, allow_popup=True, target=None, url_args=None ):
+ def __init__( self, label, key=None, condition=None, allow_multiple=True, allow_popup=True, target=None, url_args=None, async_compatible=False ):
self.label = label
self.key = key
self.allow_multiple = allow_multiple
@@ -398,6 +401,7 @@ class GridOperation( object ):
self.condition = condition
self.target = target
self.url_args = url_args
+ self.async_compatible = async_compatible
def get_url_args( self, item ):
if self.url_args:
temp = dict( self.url_args )
diff --git a/run.sh b/run.sh
index fe49fbef491..cddfde470fe 100755
--- a/run.sh
+++ b/run.sh
@@ -1,4 +1,23 @@
#!/bin/sh
cd `dirname $0`
+
+# explicitly attempt to fetch eggs before running
+FETCH_EGGS=1
+for arg in "$@"; do
+ [ "$arg" = "--stop-daemon" ] && FETCH_EGGS=0; break
+done
+if [ $FETCH_EGGS -eq 1 ]; then
+ python -ES ./scripts/check_eggs.py quiet
+ if [ $? -ne 0 ]; then
+ echo "Some eggs are out of date, attempting to fetch..."
+ python -ES ./scripts/fetch_eggs.py
+ if [ $? -eq 0 ]; then
+ echo "Fetch successful."
+ else
+ echo "Fetch failed."
+ exit 1
+ fi
+ fi
+fi
python -ES ./scripts/paster.py serve universe_wsgi.ini $@
diff --git a/scripts/check_eggs.py b/scripts/check_eggs.py
index 578be4477e7..09a77cb1e6f 100644
--- a/scripts/check_eggs.py
+++ b/scripts/check_eggs.py
@@ -11,6 +11,12 @@ root.addHandler( logging.StreamHandler( sys.stdout ) )
lib = os.path.abspath( os.path.join( os.path.dirname( __file__ ), "..", "lib" ) )
sys.path.append( lib )
+try:
+ assert sys.argv[1] == 'quiet'
+ quiet = True
+except:
+ quiet = False
+
from galaxy.eggs import *
c = Crate()
@@ -21,7 +27,9 @@ for name in c.get_names():
if not galaxy_config.check_conditional( name ):
ignore.append( name )
if not c.find( ignore=ignore ):
- print "Some of your Galaxy eggs are out of date. Please update them"
- print "by running:"
- print " python scripts/fetch_eggs.py"
+ if not quiet:
+ print "Some of your Galaxy eggs are out of date. Please update them"
+ print "by running:"
+ print " python scripts/fetch_eggs.py"
sys.exit( 1 )
+sys.exit( 0 )
diff --git a/scripts/check_python.py b/scripts/check_python.py
index 69f6f464323..1788352732d 100644
--- a/scripts/check_python.py
+++ b/scripts/check_python.py
@@ -1,19 +1,16 @@
import os, sys
+msg = """ERROR: Your Python version is: %s
+Galaxy is currently supported on Python 2.4, 2.5 and 2.6. To run Galaxy,
+please download and install a supported version from python.org. If a
+supported version is installed but is not your default, getgalaxy.org
+contains instructions on how to force Galaxy to use a different version.""" % sys.version[:3]
+
def check_python():
- return
try:
- assert sys.version_info[:2] >= ( 2, 4 ) and sys.version_info[:2] <= ( 2, 5 )
+ assert sys.version_info[:2] >= ( 2, 4 ) and sys.version_info[:2] <= ( 2, 6 )
except AssertionError:
- print >>sys.stderr, "ERROR: Your Python version is:", sys.version.split( ' ', 1 )[0]
- print >>sys.stderr, "Galaxy is currently only supported on Python 2.4 and Python 2.5."
- if sys.version_info[:2] < ( 2, 4 ):
- print >>sys.stderr, "To run Galaxy, please download and install Python 2.5 from http://python.org"
- else:
- print >>sys.stderr, "To track the progress of Python 2.6 support, please see:"
- print >>sys.stderr, " http://bitbucket.org/galaxy/galaxy-central/issue/76/support-python-26"
- print >>sys.stderr, "For hints on how to direct Galaxy to use a different python installation, see:"
- print >>sys.stderr, " http://bitbucket.org/galaxy/galaxy-central/wiki/GetGalaxy"
+ print >>sys.stderr, msg
raise
if __name__ == '__main__':
diff --git a/scripts/cleanup_datasets/cleanup_datasets.py b/scripts/cleanup_datasets/cleanup_datasets.py
index 0cd7fed5063..a9606be76d6 100644
--- a/scripts/cleanup_datasets/cleanup_datasets.py
+++ b/scripts/cleanup_datasets/cleanup_datasets.py
@@ -276,7 +276,7 @@ def purge_datasets( app, cutoff_time, remove_from_disk, info_only = False, force
app.model.Dataset.table.c.update_time < cutoff_time ) )
for dataset in datasets:
file_size = dataset.file_size
- _purge_dataset( dataset, remove_from_disk, info_only = info_only )
+ _purge_dataset( app, dataset, remove_from_disk, info_only = info_only )
dataset_count += 1
try:
disk_space += file_size
@@ -349,7 +349,7 @@ def _delete_dataset( dataset, app, remove_from_disk, info_only=False, is_deletab
app.sa_session.add( dataset )
app.sa_session.flush()
-def _purge_dataset( dataset, remove_from_disk, info_only = False ):
+def _purge_dataset( app, dataset, remove_from_disk, info_only = False ):
if dataset.deleted:
try:
if dataset.purgable and _dataset_is_deletable( dataset ):
diff --git a/scripts/scramble/scripts/pysqlite.py b/scripts/scramble/scripts/pysqlite.py
index 0c97eee5256..fc8d2b2b2c8 100644
--- a/scripts/scramble/scripts/pysqlite.py
+++ b/scripts/scramble/scripts/pysqlite.py
@@ -1,18 +1,4 @@
-import os, sys, subprocess, tarfile, zipfile, shutil
-
-def unpack_sqlite_source():
- print "unpack_sqlite_source(): Found a previously downloaded sqlite source."
- print "unpack_sqlite_source(): To force a new download, remove the archive:"
- print " ", SQLITE_ARCHIVE
- os.makedirs( "sqlite" )
- z = zipfile.ZipFile( SQLITE_ARCHIVE, "r" )
- for fn in z.namelist():
- if fn == "tclsqlite.c" or fn == "shell.c" or fn == "icu.c":
- continue
- o = open( os.path.join( "sqlite", fn ), "wb" )
- o.write( z.read( fn ) )
- o.close()
- z.close()
+import os, sys, shutil
# change back to the build dir
if os.path.dirname( sys.argv[0] ) != "":
@@ -38,42 +24,16 @@ if os.access( ".galaxy_tag", os.F_OK ):
else:
tag = None
-SQLITE_VERSION = ( tag.split( "_" ) )[1]
-SQLITE_ARCHIVE = os.path.abspath( os.path.join( "..", "..", "..", "archives", "sqlite-source-%s.zip" %SQLITE_VERSION.replace( ".", "_" ) ) )
-
# clean, in case you're running this by hand from a dirty module source dir
for dir in [ "build", "dist", "sqlite" ]:
if os.access( dir, os.F_OK ):
print "scramble_it.py: removing dir:", dir
shutil.rmtree( dir )
-# build/unpack SQLite
-unpack_sqlite_source()
-
-# changes to setup.py
-file = "setup.py"
-print "build(): Patching", file
-if not os.access( "%s.orig" %file, os.F_OK ):
- shutil.copyfile( file, "%s.orig" %file )
-i = open( "%s.orig" %file, "r" )
-o = open( file, "w" )
-for line in i.readlines():
- if line == ' "src/util.c", "src/row.c"]\n':
- line += 'sources += glob.glob("./sqlite/*.c")\n'
- if line == "include_dirs = []\n":
- line = "include_dirs = [ './sqlite' ]\n"
- if line == "define_macros = []\n":
- line = "define_macros = [ ('THREADSAFE','1') ]\n"
- print >>o, line,
-i.close()
-o.close()
-
-# don't want setup.cfg
-os.rename( "setup.cfg", "setup.cfg.orig" )
-
# tag
me = sys.argv[0]
sys.argv = [ me ]
+sys.argv.append( "build_static" )
if tag is not None:
sys.argv.append( "egg_info" )
sys.argv.append( "--tag-build=%s" %tag )
diff --git a/scripts/set_metadata.py b/scripts/set_metadata.py
index c0bea59d325..5c14dc71ada 100644
--- a/scripts/set_metadata.py
+++ b/scripts/set_metadata.py
@@ -25,6 +25,7 @@ import galaxy.model.mapping #need to load this before we unpickle, in order to s
galaxy.model.Job() #this looks REAL stupid, but it is REQUIRED in order for SA to insert parameters into the classes defined by the mappers --> it appears that instantiating ANY mapper'ed class would suffice here
galaxy.datatypes.metadata.DATABASE_CONNECTION_AVAILABLE = False #Let metadata know that there is no database connection, and to just assume object ids are valid
from galaxy.util import stringify_dictionary_keys
+from galaxy.util.json import from_json_string
from sqlalchemy.orm import clear_mappers
def __main__():
@@ -37,13 +38,25 @@ def __main__():
config_root = sys.argv.pop( 1 )
datatypes_config = sys.argv.pop( 1 )
galaxy.model.set_datatypes_registry( galaxy.datatypes.registry.Registry( config_root, datatypes_config ) )
-
+
+ job_metadata = sys.argv.pop( 1 )
+ ext_override = dict()
+ if job_metadata != "None" and os.path.exists( job_metadata ):
+ for line in open( job_metadata, 'r' ):
+ try:
+ line = stringify_dictionary_keys( from_json_string( line ) )
+ assert line['type'] == 'dataset'
+ ext_override[line['dataset_id']] = line['ext']
+ except:
+ continue
for filenames in sys.argv[1:]:
filename_in, filename_kwds, filename_out, filename_results_code, dataset_filename_override = filenames.split( ',' )
try:
dataset = cPickle.load( open( filename_in ) ) #load DatasetInstance
if dataset_filename_override:
dataset.dataset.external_filename = dataset_filename_override
+ if ext_override.get( dataset.dataset.id, None ):
+ dataset.extension = ext_override[ dataset.dataset.id ]
kwds = stringify_dictionary_keys( simplejson.load( open( filename_kwds ) ) )#load kwds; need to ensure our keywords are not unicode
dataset.datatype.set_meta( dataset, **kwds )
dataset.metadata.to_JSON_dict( filename_out ) # write out results of set_meta
diff --git a/static/scripts/galaxy.base.js b/static/scripts/galaxy.base.js
index a19b877fbbc..aaeca1a1329 100644
--- a/static/scripts/galaxy.base.js
+++ b/static/scripts/galaxy.base.js
@@ -19,6 +19,12 @@ jQuery(document).ready( function() {
jQuery( "a[confirm]" ).click( function() {
return confirm( jQuery(this).attr( "confirm" ) )
});
+ // Make popup menus.
+ make_popup_menus();
+});
+
+function make_popup_menus()
+{
jQuery( "div[popupmenu]" ).each( function() {
var options = {};
$(this).find( "a" ).each( function() {
@@ -40,7 +46,7 @@ jQuery(document).ready( function() {
$(this).remove();
b.show();
});
-});
+}
function ensure_popup_helper() {
// And the helper below the popup menus
@@ -103,3 +109,15 @@ function attach_popupmenu( button_element, wrapper ) {
};
$( button_element ).click( click );
};
+
+// 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;
+};
diff --git a/templates/admin/forms/edit_form.mako b/templates/admin/forms/edit_form.mako
index 0a910956a77..853e080895c 100644
--- a/templates/admin/forms/edit_form.mako
+++ b/templates/admin/forms/edit_form.mako
@@ -85,7 +85,7 @@ $( function() {
Edit form definition "${form.name}"
-
diff --git a/templates/grid_base_async.mako b/templates/grid_base_async.mako
new file mode 100644
index 00000000000..8f936d1efc7
--- /dev/null
+++ b/templates/grid_base_async.mako
@@ -0,0 +1,698 @@
+<%!
+ from galaxy.web.framework.helpers.grids import TextColumn
+ from galaxy.model import History, HistoryDatasetAssociation, User, Role, Group
+ import galaxy.util
+ def inherit(context):
+ if context.get('use_panels'):
+ return '/base_panels.mako'
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
+
+## Render the grid's basic elements. Each of these elements can be subclassed.
+%if message:
+
+ ## Data columns
+ %for column in grid.columns:
+ %if column.visible:
+ <%
+ # Link
+ link = column.get_link( trans, grid, item )
+ if link:
+ href = url( **link )
+ else:
+ href = None
+ # Value (coerced to list so we can loop)
+ value = column.get_value( trans, grid, item )
+ if column.ncells == 1:
+ value = [ value ]
+ %>
+ %for cellnum, v in enumerate( value ):
+ <%
+ # Handle non-ascii chars.
+ if isinstance(v, str):
+ v = unicode(v, 'utf-8')
+ # Attach popup menu?
+ if column.attach_popup and cellnum == 0:
+ extra = '▼' % i
+ else:
+ extra = ""
+ %>
+ %if href:
+
+ ## Carry forward filtering criteria with hidden inputs.
+ %for temp_column in grid.columns:
+ %if temp_column.key in cur_filter_dict:
+ <% value = cur_filter_dict[ temp_column.key ] %>
+ %if value != "All":
+ <%
+ if isinstance( temp_column, TextColumn ):
+ value = h.to_json_string( value )
+ %>
+
+ %endif
+ %endif
+ %endfor
+
+ ## Print current filtering criteria and links to delete.
+
+ %if column.key in cur_filter_dict:
+ <% column_filter = cur_filter_dict[column.key] %>
+ %if isinstance( column_filter, basestring ):
+ %if column_filter != "All":
+ ${cur_filter_dict[column.key]}
+ <% filter_all = GridColumnFilter( "", { column.key : "All" } ) %>
+
+ |
+ %endif
+ %elif isinstance( column_filter, list ):
+ %for i, filter in enumerate( column_filter ):
+ %if i > 0:
+ ,
+ %endif
+ ${filter}
+ <%
+ new_filter = list( column_filter )
+ del new_filter[ i ]
+ new_column_filter = GridColumnFilter( "", { column.key : h.to_json_string( new_filter ) } )
+ %>
+
+ %endfor
+
+ %endif
+ %endif
+
+
+ ## Print input field for column.
+
+
+ %else:
+
+ %for i, filter in enumerate( column.get_accepted_filters() ):
+ <%
+ # HACK: we know that each filter will have only a single argument, so get that single argument.
+ for key, arg in filter.args.items():
+ filter_key = key
+ filter_arg = arg
+ %>
+ %if i > 0:
+ |
+ %endif
+ %if column.key in cur_filter_dict and column.key in filter.args and cur_filter_dict[column.key] == filter.args[column.key]:
+ ${filter.label}
+ %else:
+
+ ${filter.label}
+
+ %endif
+ %endfor
+
+ %endif
+
+ ## Clear the standard search.
+ ##|
+ ##<% filter_all = GridColumnFilter( "", { column.key : "All" } ) %>
+ ##Clear All
+
+ ## Only show advanced search if there are filterable columns.
+ <%
+ show_advanced_search = False
+ for column in grid.columns:
+ if column.filterable == "advanced":
+ show_advanced_search = True
+ break
+ endif
+ %>
+ %if show_advanced_search:
+ | Advanced Search
+ %endif
+
+
+
+
+ ## Advanced search.
+
+
+
+ Advanced Search |
+ Close |
+ ## Link to clear all filters.
+ <%
+ no_filter = GridColumnFilter("Clear All", default_filter_dict)
+ %>
+ ${no_filter.label}
+
+ %for column in grid.columns:
+ %if column.filterable == "advanced":
+ ## Show div if current filter has value that is different from the default filter.
+ %if column.key in cur_filter_dict and column.key in default_filter_dict and \
+ cur_filter_dict[column.key] != default_filter_dict[column.key]:
+
+ %endif
+
+ ${render_ajax_grid_column_filter(column)}
+ %endif
+ %endfor
+
+
+%def>
\ No newline at end of file
diff --git a/templates/mobile/history/detail.mako b/templates/mobile/history/detail.mako
index c5c73ab90bc..3b11789314b 100644
--- a/templates/mobile/history/detail.mako
+++ b/templates/mobile/history/detail.mako
@@ -37,7 +37,7 @@
## Body for history items, extra info and actions, data "peek"
<% user, roles = trans.get_user_and_roles() %>
- %if not trans.app.security_agent.can_access_dataset( roles, data.dataset ):
+ %if not trans.user_is_admin() and not trans.app.security_agent.can_access_dataset( roles, data.dataset ):
- ## Data columns
- %for column in grid.columns:
- %if column.visible:
- <%
- # Link
- if column.link and column.link( item ):
- href = url( **column.link( item ) )
- else:
- href = None
- # Value (coerced to list so we can loop)
- value = column.get_value( trans, grid, item )
- if column.ncells == 1:
- value = [ value ]
- %>
- %for cellnum, v in enumerate( value ):
- <%
- # Attach popup menu?
- if column.attach_popup and cellnum == 0:
- extra = '▼' % i
- else:
- extra = ""
- %>
- %if href:
-
-## For selected requests:
-## %for operation in grid.operations:
-## %if operation.allow_multiple:
-##
-## %endif
-## %endfor
-##
-##
-
-
-
-%endif
+<%inherit file="/grid_base.mako"/>
\ No newline at end of file
diff --git a/templates/requests/show_request.mako b/templates/requests/show_request.mako
index 445a0457368..58a570e5f6d 100644
--- a/templates/requests/show_request.mako
+++ b/templates/requests/show_request.mako
@@ -119,7 +119,7 @@
diff --git a/templates/root/history_common.mako b/templates/root/history_common.mako
index a2e3597c21e..6a6a0d62356 100644
--- a/templates/root/history_common.mako
+++ b/templates/root/history_common.mako
@@ -9,7 +9,7 @@
data_state = data.state
user, roles = trans.get_user_and_roles()
%>
- %if not trans.app.security_agent.can_access_dataset( roles, data.dataset ):
+ %if not trans.user_is_admin() and not trans.app.security_agent.can_access_dataset( roles, data.dataset ):
%else:
@@ -49,7 +49,7 @@
## Body for history items, extra info and actions, data "peek"
- %if not trans.app.security_agent.can_access_dataset( roles, data.dataset ):
+ %if not trans.user_is_admin() and not trans.app.security_agent.can_access_dataset( roles, data.dataset ):
You do not have permission to view this dataset.
%elif data_state == "upload":
Dataset is uploading
diff --git a/templates/tagging_common.mako b/templates/tagging_common.mako
index 26bda0c8570..9bb09751265 100644
--- a/templates/tagging_common.mako
+++ b/templates/tagging_common.mako
@@ -23,19 +23,6 @@
else: ## isInstance( tag_name, unicode ):
tag_names_and_values[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;
-
- var count = 0;
- for (element in an_array)
- count++;
- return count;
- };
//
// Default function get text to display on the toggle link.
diff --git a/templates/tool_form.mako b/templates/tool_form.mako
index 5e49c45ccbc..d80873ffb82 100644
--- a/templates/tool_form.mako
+++ b/templates/tool_form.mako
@@ -221,11 +221,17 @@ function checkUncheckAll( name, check )
%if tool.help:
- %if tool.has_multiple_pages:
- ${tool.help_by_page[tool_state.page]}
- %else:
- ${tool.help}
- %endif
+ <%
+ if tool.has_multiple_pages:
+ tool_help = tool.help_by_page[tool_state.page]
+ else:
+ tool_help = tool.help
+
+ # Convert to unicode to display non-ascii characters.
+ if type( tool_help ) is not unicode:
+ tool_help = unicode( tool_help, 'utf-8')
+ %>
+ ${tool_help}
%endif
diff --git a/test/base/twilltestcase.py b/test/base/twilltestcase.py
index 98bd8d6fc73..2b9d6947bb9 100644
--- a/test/base/twilltestcase.py
+++ b/test/base/twilltestcase.py
@@ -10,6 +10,7 @@ from twill.other_packages._mechanize_dist import ClientForm
pkg_resources.require( "elementtree" )
from elementtree import ElementTree
from galaxy.web import security
+from galaxy.web.framework.helpers import iff
buffer = StringIO.StringIO()
@@ -180,7 +181,7 @@ class TwillTestCase( unittest.TestCase ):
num_deleted = len( id.split( ',' ) )
self.home()
self.visit_page( "history/list?operation=delete&id=%s" % ( id ) )
- check_str = 'Deleted %d histories' % num_deleted
+ check_str = 'Deleted %d %s' % ( num_deleted, iff( num_deleted != 1, "histories","history") )
self.check_page_for_string( check_str )
self.home()
def delete_current_history( self, check_str='' ):
@@ -429,6 +430,12 @@ class TwillTestCase( unittest.TestCase ):
if check_str:
self.check_page_for_string( check_str )
self.home()
+ def view_history( self, history_id, check_str='' ):
+ """Displays a history for viewing"""
+ self.visit_url( '%s/history/view?id=%s' % ( self.url, self.security.encode_id( history_id ) ) )
+ if check_str:
+ self.check_page_for_string( check_str )
+ self.home()
def edit_hda_attribute_info( self, hda_id, new_name='', new_info='', new_dbkey='', new_startcol='' ):
"""Edit history_dataset_association attribute information"""
self.home()
@@ -1162,24 +1169,24 @@ class TwillTestCase( unittest.TestCase ):
self.check_page_for_string( desc )
self.check_page_for_string( formtype )
self.home()
- def edit_form( self, form_id, form_name, new_form_name="Form One's Name (Renamed)", new_form_desc="This is Form One's description (Re-described)"):
+ def edit_form( self, form_current_id, form_name, new_form_name="Form One's Name (Renamed)", new_form_desc="This is Form One's description (Re-described)"):
"""
Edit form details; name & description
"""
self.home()
- self.visit_url( "%s/forms/edit?form_id=%i&show_form=True" % (self.url, form_id) )
+ self.visit_url( "%s/forms/manage?sort=create_time&f-name=All&f-desc=All&f-deleted=False&operation=Edit&id=%s" % ( self.url, self.security.encode_id(form_current_id) ) )
self.check_page_for_string( 'Edit form definition "%s"' % form_name )
tc.fv( "1", "name", new_form_name )
tc.fv( "1", "description", new_form_desc )
tc.submit( "save_changes_button" )
self.check_page_for_string( "The form '%s' has been updated with the changes." % new_form_name )
self.home()
- def form_add_field( self, form_id, form_name, form_desc, form_type, field_index, fields):
+ def form_add_field( self, form_current_id, form_name, form_desc, form_type, field_index, fields):
"""
Add a new fields to the form definition
"""
self.home()
- self.visit_url( "%s/forms/edit?form_id=%i&show_form=True" % (self.url, form_id) )
+ self.visit_url( "%s/forms/manage?sort=create_time&f-name=All&f-desc=All&f-deleted=False&operation=Edit&id=%s" % ( self.url, self.security.encode_id(form_current_id) ) )
self.check_page_for_string( 'Edit form definition "%s"' % form_name)
for i, field in enumerate(fields):
index = i+field_index
@@ -1191,8 +1198,8 @@ class TwillTestCase( unittest.TestCase ):
if field['type'] == 'SelectField':
options = ''
for option_index, option in enumerate(field['selectlist']):
- url_str = "%s/forms/edit?description=%s&form_id=%i&form_type_selectbox=%s&addoption_%i=Add&name=%s&field_name_%i=%s&field_helptext_%i=%s&field_type_%i=%s" % \
- (self.url, form_desc.replace(" ", "+"), form_id, form_type.replace(" ", "+"),
+ url_str = "%s/forms/manage?operation=Edit&description=%s&id=%s&form_type_selectbox=%s&addoption_%i=Add&name=%s&field_name_%i=%s&field_helptext_%i=%s&field_type_%i=%s" % \
+ (self.url, form_desc.replace(" ", "+"), self.security.encode_id(form_current_id), form_type.replace(" ", "+"),
index, form_name.replace(" ", "+"), index, field['name'].replace(" ", "+"),
index, field['desc'].replace(" ", "+"), index, field['type'])
self.visit_url( url_str + options )
@@ -1207,7 +1214,7 @@ class TwillTestCase( unittest.TestCase ):
Remove a field from the form definition
"""
self.home()
- self.visit_url( "%s/forms/edit?form_id=%i&show_form=True" % (self.url, form_id) )
+ self.visit_url( "%s/forms/manage?operation=Edit&form_id=%i&show_form=True" % (self.url, form_id) )
self.check_page_for_string( 'Edit form definition "%s"' % form_name)
tc.submit( "remove_button" )
tc.submit( "save_changes_button" )
@@ -1215,18 +1222,26 @@ class TwillTestCase( unittest.TestCase ):
self.check_page_for_string( check_str )
self.home()
# Requests stuff
+ def check_request_grid(self, state, request_name, deleted=False):
+ self.home()
+ self.visit_url('%s/requests/list?sort=create_time&f-state=%s&f-deleted=%s' \
+ % (self.url, state, str(deleted)))
+ self.check_page_for_string( request_name )
+ def check_request_admin_grid(self, state, request_name, deleted=False):
+ self.home()
+ self.visit_url('%s/requests_admin/list?sort=create_time&f-state=%s&f-deleted=%s' \
+ % (self.url, state, str(deleted)))
+ self.check_page_for_string( request_name )
def create_request_type( self, name, desc, request_form_id, sample_form_id, states ):
self.home()
- self.visit_url( "%s/requests_admin/request_type?create=True" % self.url )
+ self.visit_url( "%s/requests_admin/create_request_type" % self.url )
self.check_page_for_string( 'Create a new request type' )
tc.fv( "1", "name", name )
- tc.fv( "1", "description", desc )
+ tc.fv( "1", "desc", desc )
tc.fv( "1", "request_form_id", request_form_id )
tc.fv( "1", "sample_form_id", sample_form_id )
- tc.fv( "1", "num_states", str( len( states ) ) )
- tc.submit( "define_states_button" )
- self.check_page_for_string( "Create %i states for the '%s' request type" % ( len(states), name ))
for index, state in enumerate(states):
+ tc.submit( "add_state_button" )
tc.fv("1", "state_name_%i" % index, state[0])
tc.fv("1", "state_desc_%i" % index, state[1])
tc.submit( "save_request_type" )
@@ -1248,7 +1263,7 @@ class TwillTestCase( unittest.TestCase ):
self.check_page_for_string( desc )
def edit_request( self, request_id, name, new_name, new_desc, new_library_id, new_folder_id, new_fields):
self.home()
- self.visit_url( "%s/requests/edit?request_id=%i&show=True" % (self.url, request_id) )
+ self.visit_url( "%s/requests/list?operation=Edit&id=%s" % (self.url, self.security.encode_id(request_id) ) )
self.check_page_for_string( 'Edit request "%s"' % name )
tc.fv( "1", "name", new_name )
tc.fv( "1", "desc", new_desc )
diff --git a/test/functional/test_forms_and_requests.py b/test/functional/test_forms_and_requests.py
index f317f2502ea..cf13c6872a6 100644
--- a/test/functional/test_forms_and_requests.py
+++ b/test/functional/test_forms_and_requests.py
@@ -29,6 +29,7 @@ def get_latest_form(form_name):
.filter( galaxy.model.FormDefinitionCurrent.table.c.deleted==False ) \
.order_by( galaxy.model.FormDefinitionCurrent.table.c.create_time.desc() )
for fdc in fdc_list:
+ sa_session.refresh( fdc )
sa_session.refresh( fdc.latest_form )
if form_name == fdc.latest_form.name:
return fdc.latest_form
@@ -51,7 +52,7 @@ class TestFormsAndRequests( TwillTestCase ):
# edit form & add few more fields
new_name = "Request Form (Renamed)"
new_desc = "This is Form One's Re-described"
- self.edit_form( form_one.id, form_one.name, new_form_name=new_name, new_form_desc=new_desc )
+ self.edit_form( form_one.current.id, form_one.name, new_form_name=new_name, new_form_desc=new_desc )
self.home()
self.visit_page( 'forms/manage' )
self.check_page_for_string( new_name )
@@ -73,13 +74,13 @@ class TestFormsAndRequests( TwillTestCase ):
type='TextField',
required='required')]
form_one = get_latest_form(form_one_name)
- self.form_add_field(form_one.id, form_one.name, form_one.desc, form_one.type, field_index=len(form_one.fields), fields=fields)
- form_one_latest = get_latest_form(form_one_name)
+ self.form_add_field(form_one.current.id, form_one.name, form_one.desc, form_one.type, field_index=len(form_one.fields), fields=fields)
+ form_one_latest = get_latest_form(form_one_name)
assert len(form_one_latest.fields) == len(form_one.fields)+len(fields)
def test_015_create_sample_form( self ):
"""Testing creating another form (for samples)"""
global form_two_name
- desc = "This is Form One's description"
+ desc = "This is Form Two's description"
formtype = 'Sequencing Sample Form'
self.create_form( name=form_two_name, desc=desc, formtype=formtype )
self.home()
@@ -207,16 +208,12 @@ class TestFormsAndRequests( TwillTestCase ):
request_one.desc+' (Re-described)', library_one.id, folder_one.id, fields)
sa_session.refresh( request_one )
# check if the request is showing in the 'unsubmitted' filter
- self.home()
- self.visit_url( '%s/requests/list?show_filter=Unsubmitted' % self.url )
- self.check_page_for_string( request_one.name )
+ self.check_request_grid(state='Unsubmitted', request_name=request_one.name)
# submit the request
self.submit_request( request_one.id, request_one.name )
sa_session.refresh( request_one )
# check if the request is showing in the 'submitted' filter
- self.home()
- self.visit_url( '%s/requests/list?show_filter=Submitted' % self.url )
- self.check_page_for_string( request_one.name )
+ self.check_request_grid(state='Submitted', request_name=request_one.name)
# check if the request's state is now set to 'submitted'
assert request_one.state is not request_one.states.SUBMITTED, "The state of the request '%s' should be set to '%s'" \
% ( request_one.name, request_one.states.SUBMITTED )
@@ -225,9 +222,7 @@ class TestFormsAndRequests( TwillTestCase ):
# goto admin manage requests page
self.logout()
self.login( email='test@bx.psu.edu' )
- self.home()
- self.visit_page( 'requests_admin/list' )
- self.check_page_for_string( request_one.name )
+ self.check_request_admin_grid(state='Submitted', request_name=request_one.name)
self.visit_url( "%s/requests_admin/list?sort=-create_time&operation=show_request&id=%s" \
% ( self.url, self.security.encode_id( request_one.id ) ))
self.check_page_for_string( 'Sequencing Request "%s"' % request_one.name )
@@ -240,9 +235,10 @@ class TestFormsAndRequests( TwillTestCase ):
self.change_sample_state( sample.name, sample.id, request_type.states[2].id, request_type.states[2].name )
self.home()
sa_session.refresh( request_one )
+ self.logout()
+ self.login( email='test1@bx.psu.edu' )
# check if the request's state is now set to 'complete'
- self.visit_url('%s/requests_admin/list?show_filter=Complete' % self.url)
- self.check_page_for_string( request_one.name )
+ self.check_request_grid(state='Complete', request_name=request_one.name)
assert request_one.state is not request_one.states.COMPLETE, "The state of the request '%s' should be set to '%s'" \
% ( request_one.name, request_one.states.COMPLETE )
def test_040_admin_create_request_on_behalf_of_regular_user( self ):
@@ -262,9 +258,7 @@ class TestFormsAndRequests( TwillTestCase ):
galaxy.model.Request.table.c.deleted==False ) ) \
.first()
# check if the request is showing in the 'unsubmitted' filter
- self.home()
- self.visit_url( '%s/requests_admin/list?show_filter=Unsubmitted' % self.url )
- self.check_page_for_string( request_two.name )
+ self.check_request_admin_grid(state='Unsubmitted', request_name=request_two.name)
# check if the request's state is now set to 'unsubmitted'
assert request_two.state is not request_two.states.UNSUBMITTED, "The state of the request '%s' should be set to '%s'" \
% ( request_two.name, request_two.states.UNSUBMITTED )
@@ -277,17 +271,13 @@ class TestFormsAndRequests( TwillTestCase ):
self.submit_request_as_admin( request_two.id, request_two.name )
sa_session.refresh( request_two )
# check if the request is showing in the 'submitted' filter
- self.home()
- self.visit_url( '%s/requests_admin/list?show_filter=Submitted' % self.url )
- self.check_page_for_string( request_two.name )
+ self.check_request_admin_grid(state='Submitted', request_name=request_two.name)
# check if the request's state is now set to 'submitted'
assert request_two.state is not request_two.states.SUBMITTED, "The state of the request '%s' should be set to '%s'" \
% ( request_two.name, request_two.states.SUBMITTED )
# check if both the requests is showing in the 'All' filter
- self.home()
- self.visit_url( '%s/requests_admin/list?show_filter=All' % self.url )
- self.check_page_for_string( request_one.name )
- self.check_page_for_string( request_two.name )
+ self.check_request_admin_grid(state='All', request_name=request_one.name)
+ self.check_request_admin_grid(state='All', request_name=request_two.name)
def test_045_reject_request( self ):
'''Testing rejecting a request'''
self.logout()
@@ -295,9 +285,7 @@ class TestFormsAndRequests( TwillTestCase ):
self.reject_request( request_two.id, request_two.name )
sa_session.refresh( request_two )
# check if the request is showing in the 'unsubmitted' filter
- self.home()
- self.visit_url( '%s/requests_admin/list?show_filter=Unsubmitted' % self.url )
- self.check_page_for_string( request_two.name )
+ self.check_request_admin_grid(state='Unsubmitted', request_name=request_two.name)
# check if the request's state is now set to 'submitted'
assert request_two.state is not request_two.states.UNSUBMITTED, "The state of the request '%s' should be set to '%s'" \
% ( request_two.name, request_two.states.UNSUBMITTED )
diff --git a/test/functional/test_get_data.py b/test/functional/test_get_data.py
index 196d07d8b4b..36a9b0fac26 100644
--- a/test/functional/test_get_data.py
+++ b/test/functional/test_get_data.py
@@ -4,128 +4,538 @@ from galaxy.model.mapping import context as sa_session
from base.twilltestcase import TwillTestCase
class UploadData( TwillTestCase ):
- def test_000_upload_files_from_disk( self ):
- """Test uploading data files from disk"""
+ def test_0005_upload_file( self ):
+ """Test uploading 1.bed, NOT setting the file format"""
self.logout()
self.login( email='test@bx.psu.edu' )
global admin_user
admin_user = sa_session.query( galaxy.model.User ) \
.filter( galaxy.model.User.table.c.email=='test@bx.psu.edu' ) \
.one()
- history1 = sa_session.query( galaxy.model.History ) \
- .filter( and_( galaxy.model.History.table.c.deleted==False,
- galaxy.model.History.table.c.user_id==admin_user.id ) ) \
- .order_by( desc( galaxy.model.History.table.c.create_time ) ) \
- .first()
+ history = sa_session.query( galaxy.model.History ) \
+ .filter( and_( galaxy.model.History.table.c.deleted==False,
+ galaxy.model.History.table.c.user_id==admin_user.id ) ) \
+ .order_by( desc( galaxy.model.History.table.c.create_time ) ) \
+ .first()
self.upload_file( '1.bed' )
- hda1 = sa_session.query( galaxy.model.HistoryDatasetAssociation ) \
- .order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ) \
- .first()
- assert hda1 is not None, "Problem retrieving hda1 from database"
- self.verify_dataset_correctness( '1.bed', hid=str( hda1.hid ) )
- self.upload_file( '2.bed', dbkey='hg17' )
- hda2 = sa_session.query( galaxy.model.HistoryDatasetAssociation ) \
- .order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ) \
- .first()
- assert hda2 is not None, "Problem retrieving hda2 from database"
- self.verify_dataset_correctness( '2.bed', hid=str( hda2.hid ) )
- self.upload_file( '3.bed', dbkey='hg17', ftype='bed' )
- hda3 = sa_session.query( galaxy.model.HistoryDatasetAssociation ) \
- .order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ) \
- .first()
- assert hda3 is not None, "Problem retrieving hda3 from database"
- self.verify_dataset_correctness( '3.bed', hid=str( hda3.hid ) )
+ hda = sa_session.query( galaxy.model.HistoryDatasetAssociation ) \
+ .order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ) \
+ .first()
+ assert hda is not None, "Problem retrieving hda from database"
+ self.verify_dataset_correctness( '1.bed', hid=str( hda.hid ) )
+ self.check_history_for_string( "