galaxy-commits
Threads by month
- ----- 2025 -----
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/ca59bd157bba/
changeset: ca59bd157bba
branches:
user: kanwei
date: 2011-06-03 22:22:02
summary: tab -> spaces
affected #: 1 file (70 bytes)
--- a/tools/ngs_rna/tophat_wrapper.xml Fri Jun 03 16:09:01 2011 -0400
+++ b/tools/ngs_rna/tophat_wrapper.xml Fri Jun 03 16:22:02 2011 -0400
@@ -513,7 +513,7 @@
<param name="sPaired" value="single"/><param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger"/><param name="sSettingsType" value="full"/>
- <param name="library_type" value="FR Unstranded"/>
+ <param name="library_type" value="FR Unstranded"/><param name="anchor_length" value="8"/><param name="splice_mismatches" value="0"/><param name="min_intron_length" value="70"/>
@@ -525,8 +525,8 @@
<param name="seg_mismatches" value="2"/><param name="seg_length" value="25"/><param name="allow_indel_search" value="Yes"/>
- <param name="max_insertion_length" value="3"/>
- <param name="max_deletion_length" value="3"/>
+ <param name="max_insertion_length" value="3"/>
+ <param name="max_deletion_length" value="3"/><param name="use_junctions" value="Yes" /><param name="use_annotations" value="No" /><param name="use_juncs" value="No" />
@@ -557,7 +557,7 @@
<param name="input2" ftype="fastqsanger" value="tophat_in3.fastqsanger"/><param name="mate_inner_distance" value="20"/><param name="pSettingsType" value="full"/>
- <param name="library_type" value="FR Unstranded"/>
+ <param name="library_type" value="FR Unstranded"/><param name="mate_std_dev" value="20"/><param name="anchor_length" value="8"/><param name="splice_mismatches" value="0"/>
@@ -637,13 +637,13 @@
-r This is the expected (mean) inner distance between mate pairs. For, example, for paired end runs with fragments
selected at 300bp, where each end is 50bp, you should set -r to be 200. There is no default, and this parameter
is required for paired end runs.
- --mate-std-dev INT The standard deviation for the distribution on inner distances between mate pairs. The default is 20bp.
- -a/--min-anchor-length INT The "anchor length". TopHat will report junctions spanned by reads with at least this many bases on each side of the junction. Note that individual spliced
+ --mate-std-dev INT The standard deviation for the distribution on inner distances between mate pairs. The default is 20bp.
+ -a/--min-anchor-length INT The "anchor length". TopHat will report junctions spanned by reads with at least this many bases on each side of the junction. Note that individual spliced
alignments may span a junction with fewer than this many bases on one side. However, every junction involved in spliced alignments is supported by at least one
- read with this many bases on each side. This must be at least 3 and the default is 8.
- -m/--splice-mismatches INT The maximum number of mismatches that may appear in the "anchor" region of a spliced alignment. The default is 0.
- -i/--min-intron-length INT The minimum intron length. TopHat will ignore donor/acceptor pairs closer than this many bases apart. The default is 70.
- -I/--max-intron-length INT The maximum intron length. When searching for junctions ab initio, TopHat will ignore donor/acceptor pairs farther than this many bases apart, except when such a pair is supported by a split segment alignment of a long read. The default is 500000.
+ read with this many bases on each side. This must be at least 3 and the default is 8.
+ -m/--splice-mismatches INT The maximum number of mismatches that may appear in the "anchor" region of a spliced alignment. The default is 0.
+ -i/--min-intron-length INT The minimum intron length. TopHat will ignore donor/acceptor pairs closer than this many bases apart. The default is 70.
+ -I/--max-intron-length INT The maximum intron length. When searching for junctions ab initio, TopHat will ignore donor/acceptor pairs farther than this many bases apart, except when such a pair is supported by a split segment alignment of a long read. The default is 500000.
-F/--min-isoform-fraction 0.0-1.0 TopHat filters out junctions supported by too few alignments. Suppose a junction spanning two exons, is supported by S reads. Let the average depth of coverage of
exon A be D, and assume that it is higher than B. If S / D is less than the minimum isoform fraction, the junction is not reported. A value of zero disables the
filter. The default is 0.15.
@@ -652,20 +652,20 @@
-G/--GTF [GTF 2.2 file] Supply TopHat with a list of gene model annotations. TopHat will use the exon records in this file to build a set of known splice junctions for each gene, and will attempt to align reads to these junctions even if they would not normally be covered by the initial mapping.
-j/--raw-juncs [juncs file] Supply TopHat with a list of raw junctions. Junctions are specified one per line, in a tab-delimited format. Records look like: [chrom] [left] [right] [+/-], left and right are zero-based coordinates, and specify the last character of the left sequenced to be spliced to the first character of the right sequence, inclusive.
-no-novel-juncs Only look for junctions indicated in the supplied GFF file. (ignored without -G)
- --no-closure-search Disables the mate pair closure-based search for junctions. Currently, has no effect - closure search is off by default.
- --closure-search Enables the mate pair closure-based search for junctions. Closure-based search should only be used when the expected inner distance between mates is small (about or less than 50bp)
- --no-coverage-search Disables the coverage based search for junctions.
- --coverage-search Enables the coverage based search for junctions. Use when coverage search is disabled by default (such as for reads 75bp or longer), for maximum sensitivity.
- --microexon-search With this option, the pipeline will attempt to find alignments incident to microexons. Works only for reads 50bp or longer.
- --butterfly-search TopHat will use a slower but potentially more sensitive algorithm to find junctions in addition to its standard search. Consider using this if you expect that your experiment produced a lot of reads from pre-mRNA, that fall within the introns of your transcripts.
- --segment-mismatches Read segments are mapped independently, allowing up to this many mismatches in each segment alignment. The default is 2.
- --segment-length Each read is cut up into segments, each at least this long. These segments are mapped independently. The default is 25.
- --min-closure-exon During closure search for paired end reads, exonic hops in the potential splice graph must be at least this long. The default is 50.
- --min-closure-intron The minimum intron length that may be found during closure search. The default is 50.
- --max-closure-intron The maximum intron length that may be found during closure search. The default is 5000.
- --min-coverage-intron The minimum intron length that may be found during coverage search. The default is 50.
- --max-coverage-intron The maximum intron length that may be found during coverage search. The default is 20000.
- --min-segment-intron The minimum intron length that may be found during split-segment search. The default is 50.
- --max-segment-intron The maximum intron length that may be found during split-segment search. The default is 500000.
+ --no-closure-search Disables the mate pair closure-based search for junctions. Currently, has no effect - closure search is off by default.
+ --closure-search Enables the mate pair closure-based search for junctions. Closure-based search should only be used when the expected inner distance between mates is small (about or less than 50bp)
+ --no-coverage-search Disables the coverage based search for junctions.
+ --coverage-search Enables the coverage based search for junctions. Use when coverage search is disabled by default (such as for reads 75bp or longer), for maximum sensitivity.
+ --microexon-search With this option, the pipeline will attempt to find alignments incident to microexons. Works only for reads 50bp or longer.
+ --butterfly-search TopHat will use a slower but potentially more sensitive algorithm to find junctions in addition to its standard search. Consider using this if you expect that your experiment produced a lot of reads from pre-mRNA, that fall within the introns of your transcripts.
+ --segment-mismatches Read segments are mapped independently, allowing up to this many mismatches in each segment alignment. The default is 2.
+ --segment-length Each read is cut up into segments, each at least this long. These segments are mapped independently. The default is 25.
+ --min-closure-exon During closure search for paired end reads, exonic hops in the potential splice graph must be at least this long. The default is 50.
+ --min-closure-intron The minimum intron length that may be found during closure search. The default is 50.
+ --max-closure-intron The maximum intron length that may be found during closure search. The default is 5000.
+ --min-coverage-intron The minimum intron length that may be found during coverage search. The default is 50.
+ --max-coverage-intron The maximum intron length that may be found during coverage search. The default is 20000.
+ --min-segment-intron The minimum intron length that may be found during split-segment search. The default is 50.
+ --max-segment-intron The maximum intron length that may be found during split-segment search. The default is 500000.
</help></tool>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

03 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/734e145779e4/
changeset: 734e145779e4
branches:
user: kanwei
date: 2011-06-03 22:09:01
summary: Add dataset used for blastxml unit test
affected #: 1 file (0 bytes)
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/7ee052a1f4f2/
changeset: 7ee052a1f4f2
branches:
user: kanwei
date: 2011-06-03 22:08:26
summary: Grouping tool:
- Converted to use numpy, which is included with Galaxy, instead of rpy, which is not.
- Don't simply skip lines if a numeric parameter encounters non-numeric data, return descriptive error with line contents instead
- General refactoring
- Added new comprehensive test, disabled until test framework supports multiple repeat inputs
affected #: 3 files (3.3 KB)
--- a/tools/stats/grouping.py Fri Jun 03 15:36:59 2011 -0400
+++ b/tools/stats/grouping.py Fri Jun 03 16:08:26 2011 -0400
@@ -1,73 +1,58 @@
#!/usr/bin/env python
# Guruprasad Ananda
# Refactored 2011, Kanwei Li
+# Refactored to use numpy instead of rpy
"""
This tool provides the SQL "group by" functionality.
"""
-import sys, string, re, commands, tempfile, random
-from rpy import *
+import sys, commands, tempfile, random
+import pkg_resources
+pkg_resources.require( "numpy" )
+import numpy
+
from itertools import groupby
def stop_err(msg):
sys.stderr.write(msg)
sys.exit()
+def mode(data):
+ counts = {}
+ for x in data:
+ counts[x] = counts.get(x,0) + 1
+ maxcount = max(counts.values())
+ modelist = []
+ for x in counts:
+ if counts[x] == maxcount:
+ modelist.append( str(x) )
+ return ','.join(modelist)
+
def main():
inputfile = sys.argv[2]
ignorecase = int(sys.argv[4])
ops = []
cols = []
- rounds = []
- elems = []
+ round_val = []
+ data_ary = []
for var in sys.argv[5:]:
- ops.append(var.split()[0])
- cols.append(var.split()[1])
- rounds.append(var.split()[2])
-
- if 'Mode' in ops:
- try:
- r.library('prettyR')
- except:
- stop_err('R package prettyR could not be loaded. Please make sure it is installed.')
-
+ op, col, do_round = var.split()
+ ops.append(op)
+ cols.append(col)
+ round_val.append(do_round)
"""
At this point, ops, cols and rounds will look something like this:
ops: ['mean', 'min', 'c']
cols: ['1', '3', '4']
- rounds: ['no', 'yes' 'no']
+ round_val: ['no', 'yes' 'no']
"""
-
- for i, line in enumerate( file ( inputfile )):
- line = line.rstrip('\r\n')
- if len( line )>0 and not line.startswith( '#' ):
- elems = line.split( '\t' )
- break
- if i == 30:
- break # Hopefully we'll never get here...
-
- if len( elems )<1:
- stop_err( "The data in your input dataset is either missing or not formatted properly." )
-
+
try:
group_col = int( sys.argv[3] )-1
except:
stop_err( "Group column not specified." )
str_ops = ['c', 'length', 'unique', 'random', 'cuniq', 'Mode'] #ops that can handle string/non-numeric inputs
- for k, col in enumerate(cols):
- col = int(col)-1
- if ops[k] not in str_ops:
- # We'll get here only if the user didn't choose 'Concatenate' or 'Count' or 'Count Distinct' or 'pick randomly', which are the
- # only aggregation functions that can be used on columns containing strings.
- try:
- float( elems[col] )
- except:
- try:
- msg = "Operation '%s' cannot be performed on non-numeric column %d containing value '%s'." %( ops[k], col+1, elems[col] )
- except:
- msg = "Operation '%s' cannot be performed on non-numeric data." %ops[k]
- stop_err( msg )
tmpfile = tempfile.NamedTemporaryFile()
@@ -83,7 +68,7 @@
case = ''
if ignorecase == 1:
case = '-f'
- command_line = "sort -t ' ' " + case + " -k" + str(group_col+1) +"," + str(group_col+1) + " -o " + tmpfile.name + " " + inputfile
+ command_line = "sort -t ' ' %s -k%s,%s -o %s %s" % (case, group_col+1, group_col+1, tmpfile.name, inputfile)
except Exception, exc:
stop_err( 'Initialization error -> %s' %str(exc) )
@@ -92,21 +77,16 @@
if error_code != 0:
stop_err( "Sorting input dataset resulted in error: %s: %s" %( error_code, stdout ))
- prev_item = None
- skipped_lines = 0
- first_invalid_line = None
- invalid_value = ''
- invalid_column = 0
fout = open(sys.argv[1], "w")
def is_new_item(line):
item = line.strip().split("\t")[group_col]
if ignorecase == 1:
- item = item.lower()
+ return item.lower()
return item
for key, line_list in groupby(tmpfile, key=is_new_item):
- op_vals = [ [] for op in cols ]
+ op_vals = [ [] for op in ops ]
out_str = key
multiple_modes = False
mode_index = None
@@ -115,86 +95,65 @@
fields = line.strip().split("\t")
for i, col in enumerate(cols):
col = int(col)-1 # cXX from galaxy is 1-based
- val = fields[col].strip()
- # Before appending the current value, make sure it is numeric if the
- # operation for the column requires it.
- if ops[i] not in str_ops:
- try:
- float(val)
- except ValueError:
- skipped_lines += 1
- if first_invalid_line is None:
- first_invalid_line = i+1
- invalid_value = fields[col]
- invalid_column = col+1
- break
+ try:
+ val = fields[col].strip()
+ op_vals[i].append(val)
+ except IndexError:
+ sys.stderr.write( 'Could not access the value for column %s on line: "%s". Make sure file is tab-delimited.\n' % (col+1, line) )
+ sys.exit( 1 )
- op_vals[i].append(val)
+ # Generate string for each op for this group
+ for i, op in enumerate( ops ):
+ data = op_vals[i]
+ rval = ""
+ if op == "mode":
+ rval = mode( data )
+ elif op == "length":
+ rval = len( data )
+ elif op == "random":
+ rval = random.choice(data)
+ elif op in ['cat', 'cat_uniq']:
+ if op == 'cat_uniq':
+ data = numpy.unique(data)
+ rval = ','.join(data)
+ elif op == "unique":
+ rval = len( numpy.unique(data) )
+ else:
+ # some kind of numpy fn
+ try:
+ data = map(float, data)
+ except ValueError:
+ sys.stderr.write( "Operation %s expected number values but got %s instead.\n" % (op, data) )
+ sys.exit( 1 )
+ rval = getattr(numpy, op)( data )
+ if round_val[i] == 'yes':
+ rval = round(rval)
+ else:
+ rval = '%g' % rval
+
+ out_str += "\t%s" % rval
- for i, op in enumerate( ops ):
- if op == 'cuniq':
- rfunc = "r.c"
- else:
- rfunc = "r." + op
- if op not in str_ops:
- for j, elem in enumerate( op_vals[i] ):
- op_vals[i][j] = float( elem )
- rout = eval( rfunc )( op_vals[i] )
- if rounds[i] == 'yes':
- rout = round(float(rout))
- else:
- rout = '%g' %(float(rout))
- else:
- if op != 'random':
- rout = eval( rfunc )( op_vals[i] )
- else:
- try:
- rand_index = random.randint(0,len(op_vals[i])-1) #if the two inputs to randint are equal, it seems to throw a ValueError. This can't be reproduced with the python interpreter in its interactive mode.
- except:
- rand_index = 0
- rout = op_vals[i][rand_index]
-
- if op == 'Mode' and rout == '>1 mode':
- multiple_modes = True
- mode_index = i
- if op == 'unique':
- rfunc = "r.length"
- rout = eval( rfunc )( rout )
- if op in ['c', 'cuniq']:
- if isinstance(rout, list):
- if op == 'cuniq':
- rout = set(rout)
- out_str += "\t" + ','.join(rout)
- else:
- out_str += "\t" + str(rout)
- else:
- out_str += "\t" + str(rout)
- if multiple_modes and mode_index != None:
- out_str_list = out_str.split('\t')
- for val in op_vals[mode_index]:
- out_str = '\t'.join(out_str_list[:mode_index+1]) + '\t' + str(val) + '\t' + '\t'.join(out_str_list[mode_index+2:])
- fout.write(out_str.rstrip('\t') + "\n")
- else:
- fout.write(out_str + "\n")
+ fout.write(out_str + "\n")
# Generate a useful info message.
msg = "--Group by c%d: " %(group_col+1)
for i, op in enumerate(ops):
- if op == 'c':
+ if op == 'cat':
op = 'concat'
+ elif op == 'cat_uniq':
+ op = 'concat_distinct'
elif op == 'length':
op = 'count'
elif op == 'unique':
op = 'count_distinct'
elif op == 'random':
op = 'randomly_pick'
- elif op == 'cuniq':
- op = 'concat_distinct'
+
msg += op + "[c" + cols[i] + "] "
- if skipped_lines > 0:
- msg+= "--skipped %d invalid lines starting with line %d. Value '%s' in column %d is not numeric." % ( skipped_lines, first_invalid_line, invalid_value, invalid_column )
print msg
+ fout.close()
+ tmpfile.close()
if __name__ == "__main__":
main()
--- a/tools/stats/grouping.xml Fri Jun 03 15:36:59 2011 -0400
+++ b/tools/stats/grouping.xml Fri Jun 03 16:08:26 2011 -0400
@@ -1,4 +1,4 @@
-<tool id="Grouping1" name="Group" version="1.9.4">
+<tool id="Grouping1" name="Group" version="2.0.0"><description>data by a column and perform aggregate operation on other columns.</description><command interpreter="python">
grouping.py
@@ -22,16 +22,16 @@
<param name="optype" type="select" label="Type"><option value="mean">Mean</option><option value="median">Median</option>
- <option value="Mode">Mode</option>
+ <option value="mode">Mode</option><option value="max">Maximum</option><option value="min">Minimum</option><option value="sum">Sum</option><option value="length">Count</option><option value="unique">Count Distinct</option>
- <option value="c">Concatenate</option>
- <option value="cuniq">Concatenate Distinct</option>
+ <option value="cat">Concatenate</option>
+ <option value="cat_uniq">Concatenate Distinct</option><option value="random">Randomly pick</option>
- <option value="sd">Standard deviation</option>
+ <option value="std">Standard deviation</option></param><param name="opcol" label="On column" type="data_column" data_ref="input1" /><param name="opround" type="select" label="Round result to nearest integer?">
@@ -44,7 +44,7 @@
<data format="tabular" name="out_file1" /></outputs><requirements>
- <requirement type="python-module">rpy</requirement>
+ <requirement type="python-module">numpy</requirement></requirements><tests><!-- Test valid data -->
@@ -57,8 +57,16 @@
<param name="opround" value="no"/><output name="out_file1" file="groupby_out1.dat"/></test>
-
- <!-- Test data with an invalid value in a column -->
+ <!-- Long case but test framework doesn't allow yet
+ <test>
+ <param name="input1" value="1.bed"/>
+ <param name="groupcol" value="1"/>
+ <param name="ignorecase" value="false"/>
+ <param name="operations" value='[{"opcol": "2", "__index__": 0, "optype": "mean", "opround": "no"}, {"opcol": "2", "__index__": 1, "optype": "median", "opround": "no"}, {"opcol": "6", "__index__": 2, "optype": "mode", "opround": "no"}, {"opcol": "2", "__index__": 3, "optype": "max", "opround": "no"}, {"opcol": "2", "__index__": 4, "optype": "min", "opround": "no"}, {"opcol": "2", "__index__": 5, "optype": "sum", "opround": "no"}, {"opcol": "1", "__index__": 6, "optype": "length", "opround": "no"}, {"opcol": "1", "__index__": 7, "optype": "unique", "opround": "no"}, {"opcol": "1", "__index__": 8, "optype": "cat", "opround": "no"}, {"opcol": "6", "__index__": 9, "optype": "cat_uniq", "opround": "no"}, {"opcol": "2", "__index__": 10, "optype": "random", "opround": "no"}, {"opcol": "2", "__index__": 11, "optype": "std", "opround": "no"}]'/>
+ <output name="out_file1" file="groupby_out3.tabular"/>
+ </test>
+ -->
+ <!-- Test data with an invalid value in a column. Can't do it because test framework doesn't allow testing of errors
<test><param name="input1" value="1.tabular"/><param name="groupcol" value="1"/>
@@ -68,6 +76,7 @@
<param name="opround" value="no"/><output name="out_file1" file="groupby_out2.dat"/></test>
+ --></tests><help>
@@ -79,9 +88,7 @@
**Syntax**
-This tool allows you to group the input dataset by a particular column and perform aggregate functions like Mean, Median, Mode, Sum, Max, Min, Count, Random draw and Concatenate on other columns.
-
-- All invalid, blank and comment lines are skipped when performing the aggregate functions. The number of skipped lines is displayed in the resulting history item.
+This tool allows you to group the input dataset by a particular column and perform aggregate functions: Mean, Median, Mode, Sum, Max, Min, Count, Randomly pick, and Concatenate on any column.
- If multiple modes are present, all are reported.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: greg: Move duplicate data type checker methods from sniff and upload into a new ~/datatypes/checkers.py.
by Bitbucket 03 Jun '11
by Bitbucket 03 Jun '11
03 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/c2bc73b017cb/
changeset: c2bc73b017cb
branches:
user: greg
date: 2011-06-03 21:36:59
summary: Move duplicate data type checker methods from sniff and upload into a new ~/datatypes/checkers.py.
affected #: 3 files (4.4 KB)
--- a/lib/galaxy/datatypes/sniff.py Fri Jun 03 15:18:31 2011 -0400
+++ b/lib/galaxy/datatypes/sniff.py Fri Jun 03 15:36:59 2011 -0400
@@ -4,6 +4,7 @@
import logging, sys, os, csv, tempfile, shutil, re, zipfile, gzip
import registry
from galaxy import util
+from galaxy.datatypes.checkers import *
from galaxy.datatypes.binary import unsniffable_binary_formats
log = logging.getLogger(__name__)
@@ -319,59 +320,6 @@
return 'tabular' #default tabular data type file extension
return 'txt' #default text data type file extension
-
-#Methods Used below can be used to upload new datasets into Galaxy. Currently used by the data_source.py script/tools.
-#These should be further abstracted and merged with upload.py script/tool functionality.
-def is_gzip( filename ):
- temp = open( filename, "U" )
- magic_check = temp.read( 2 )
- temp.close()
- if magic_check != util.gzip_magic:
- return False
- return True
-
-
-def is_binary( filename ):
- is_binary = False
- temp = open( filename, "U" )
- chars_read = 0
- for chars in temp:
- for char in chars:
- chars_read += 1
- if ord( char ) > 128:
- is_binary = True
- break
- if chars_read > 100:
- break
- if chars_read > 100:
- break
- temp.close()
- return is_binary
-
-def is_html( temp_name, chunk=None ):
- if chunk is None:
- temp = open(temp_name, "U")
- else:
- temp = chunk
- regexp1 = re.compile( "<A\s+[^>]*HREF[^>]+>", re.I )
- regexp2 = re.compile( "<IFRAME[^>]*>", re.I )
- regexp3 = re.compile( "<FRAMESET[^>]*>", re.I )
- regexp4 = re.compile( "<META[^>]*>", re.I )
- regexp5 = re.compile( "<SCRIPT[^>]*>", re.I )
- lineno = 0
- for line in temp:
- lineno += 1
- matches = regexp1.search( line ) or regexp2.search( line ) or regexp3.search( line ) or regexp4.search( line ) or regexp5.search( line )
- if matches:
- if chunk is None:
- temp.close()
- return True
- if lineno > 100:
- break
- if chunk is None:
- temp.close()
- return False
-
def handle_compressed_file( filename, datatypes_registry, ext = 'auto' ):
CHUNK_SIZE = 2**20 # 1Mb
is_compressed = False
@@ -429,10 +377,10 @@
if ext in AUTO_DETECT_EXTENSIONS:
ext = guess_ext( filename, sniff_order = datatypes_registry.sniff_order, is_multi_byte=is_multi_byte )
- if is_binary( filename ):
+ if check_binary( filename ):
if ext not in unsniffable_binary_formats and not datatypes_registry.get_datatype_by_extension( ext ).sniff( filename ):
raise InappropriateDatasetContentError, 'The binary uploaded file contains inappropriate content.'
- elif is_html( filename ):
+ elif check_html( filename ):
raise InappropriateDatasetContentError, 'The uploaded file contains inappropriate HTML content.'
return ext
@@ -449,4 +397,3 @@
if __name__ == '__main__':
import doctest, sys
doctest.testmod(sys.modules[__name__])
-
--- a/tools/data_source/upload.py Fri Jun 03 15:18:31 2011 -0400
+++ b/tools/data_source/upload.py Fri Jun 03 15:36:59 2011 -0400
@@ -8,6 +8,7 @@
from galaxy import eggs
# need to import model before sniff to resolve a circular import dependency
import galaxy.model
+from galaxy.datatypes.checkers import *
from galaxy.datatypes import sniff
from galaxy.datatypes.binary import *
from galaxy.datatypes.images import Pdf
@@ -48,104 +49,20 @@
return [safe_dict(x) for x in d]
else:
return d
-def check_html( temp_name, chunk=None ):
- if chunk is None:
- temp = open(temp_name, "U")
- else:
- temp = chunk
- regexp1 = re.compile( "<A\s+[^>]*HREF[^>]+>", re.I )
- regexp2 = re.compile( "<IFRAME[^>]*>", re.I )
- regexp3 = re.compile( "<FRAMESET[^>]*>", re.I )
- regexp4 = re.compile( "<META[^>]*>", re.I )
- regexp5 = re.compile( "<SCRIPT[^>]*>", re.I )
- lineno = 0
- for line in temp:
- lineno += 1
- matches = regexp1.search( line ) or regexp2.search( line ) or regexp3.search( line ) or regexp4.search( line ) or regexp5.search( line )
- if matches:
- if chunk is None:
- temp.close()
- return True
- if lineno > 100:
- break
- if chunk is None:
- temp.close()
- return False
-def check_binary( temp_name ):
- is_binary = False
- temp = open( temp_name, "U" )
- chars_read = 0
- for chars in temp:
- for char in chars:
- chars_read += 1
- if ord( char ) > 128:
- is_binary = True
- break
- if chars_read > 100:
- break
- if chars_read > 100:
- break
- temp.close()
- return is_binary
-def check_bam( temp_name ):
- return Bam().sniff( temp_name )
-def check_sff( temp_name ):
- return Sff().sniff( temp_name )
-def check_pdf( temp_name ):
- return Pdf().sniff( temp_name )
-def check_bigwig( temp_name ):
- return BigWig().sniff( temp_name )
-def check_bigbed( temp_name ):
- return BigBed().sniff( temp_name )
-def check_gzip( temp_name ):
- # This method returns a tuple of booleans representing ( is_gzipped, is_valid )
- # Make sure we have a gzipped file
- try:
- temp = open( temp_name, "U" )
- magic_check = temp.read( 2 )
- temp.close()
- if magic_check != util.gzip_magic:
- return ( False, False )
- except:
- return ( False, False )
- # We support some binary data types, so check if the compressed binary file is valid
- # If the file is Bam, it should already have been detected as such, so we'll just check
- # for sff format.
- try:
- header = gzip.open( temp_name ).read(4)
- if binascii.b2a_hex( header ) == binascii.hexlify( '.sff' ):
- return ( True, True )
- except:
- return( False, False )
- CHUNK_SIZE = 2**15 # 32Kb
- gzipped_file = gzip.GzipFile( temp_name, mode='rb' )
- chunk = gzipped_file.read( CHUNK_SIZE )
- gzipped_file.close()
- # See if we have a compressed HTML file
- if check_html( temp_name, chunk=chunk ):
- return ( True, False )
- return ( True, True )
-def check_bz2( temp_name ):
- try:
- temp = open( temp_name, "U" )
- magic_check = temp.read( 3 )
- temp.close()
- if magic_check != util.bz2_magic:
- return ( False, False )
- except:
- return( False, False )
- CHUNK_SIZE = 2**15 # reKb
- bzipped_file = bz2.BZ2File( temp_name, mode='rb' )
- chunk = bzipped_file.read( CHUNK_SIZE )
- bzipped_file.close()
- # See if we have a compressed HTML file
- if check_html( temp_name, chunk=chunk ):
- return ( True, False )
- return ( True, True )
-def check_zip( temp_name ):
- if zipfile.is_zipfile( temp_name ):
- return True
- return False
+def check_bam( file_path ):
+ return Bam().sniff( file_path )
+
+def check_sff( file_path ):
+ return Sff().sniff( file_path )
+
+def check_pdf( file_path ):
+ return Pdf().sniff( file_path )
+
+def check_bigwig( file_path ):
+ return BigWig().sniff( file_path )
+
+def check_bigbed( file_path ):
+ return BigBed().sniff( file_path )
def parse_outputs( args ):
rval = {}
for arg in args:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: natefoo: Prevent upload job creation from clobbering the input if linking data into Galaxy.
by Bitbucket 03 Jun '11
by Bitbucket 03 Jun '11
03 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/38fe5eeb1d6f/
changeset: 38fe5eeb1d6f
branches:
user: natefoo
date: 2011-06-03 21:18:31
summary: Prevent upload job creation from clobbering the input if linking data into Galaxy.
affected #: 2 files (338 bytes)
--- a/lib/galaxy/jobs/__init__.py Fri Jun 03 11:25:02 2011 -0400
+++ b/lib/galaxy/jobs/__init__.py Fri Jun 03 15:18:31 2011 -0400
@@ -752,7 +752,10 @@
sizes = []
output_paths = self.get_output_fnames()
for outfile in [ str( o ) for o in output_paths ]:
- sizes.append( ( outfile, os.stat( outfile ).st_size ) )
+ if os.path.exists( outfile ):
+ sizes.append( ( outfile, os.stat( outfile ).st_size ) )
+ else:
+ sizes.append( ( outfile, 0 ) )
return sizes
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 ):
@@ -999,7 +1002,10 @@
sizes = []
output_paths = self.get_output_fnames()
for outfile in [ str( o ) for o in output_paths ]:
- sizes.append( ( outfile, os.stat( outfile ).st_size ) )
+ if os.path.exists( outfile ):
+ sizes.append( ( outfile, os.stat( outfile ).st_size ) )
+ else:
+ sizes.append( ( outfile, 0 ) )
return sizes
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 ):
--- a/lib/galaxy/tools/actions/upload_common.py Fri Jun 03 11:25:02 2011 -0400
+++ b/lib/galaxy/tools/actions/upload_common.py Fri Jun 03 15:18:31 2011 -0400
@@ -323,12 +323,14 @@
for i, dataset in enumerate( data_list ):
job.add_output_library_dataset( 'output%i' % i, dataset )
# Create an empty file immediately
- open( dataset.file_name, "w" ).close()
+ if not dataset.dataset.external_filename:
+ open( dataset.file_name, "w" ).close()
else:
for i, dataset in enumerate( data_list ):
job.add_output_dataset( 'output%i' % i, dataset )
# Create an empty file immediately
- open( dataset.file_name, "w" ).close()
+ if not dataset.dataset.external_filename:
+ open( dataset.file_name, "w" ).close()
job.state = job.states.NEW
trans.sa_session.add( job )
trans.sa_session.flush()
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: natefoo: SMTP Authentication support for all places where Galaxy sends mail. Use STARTTLS where available, too.
by Bitbucket 03 Jun '11
by Bitbucket 03 Jun '11
03 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/b6582a3018f5/
changeset: b6582a3018f5
branches:
user: natefoo
date: 2011-06-03 17:25:02
summary: SMTP Authentication support for all places where Galaxy sends mail. Use STARTTLS where available, too.
affected #: 7 files (3.8 KB)
--- a/lib/galaxy/config.py Fri Jun 03 10:16:20 2011 -0400
+++ b/lib/galaxy/config.py Fri Jun 03 11:25:02 2011 -0400
@@ -76,6 +76,8 @@
self.mailing_join_addr = kwargs.get('mailing_join_addr',"galaxy-user-join(a)bx.psu.edu")
self.error_email_to = kwargs.get( 'error_email_to', None )
self.smtp_server = kwargs.get( 'smtp_server', None )
+ self.smtp_username = kwargs.get( 'smtp_username', None )
+ self.smtp_password = kwargs.get( 'smtp_password', None )
self.start_job_runners = kwargs.get( 'start_job_runners', None )
# External Service types used in sample tracking
self.external_service_type_config_file = resolve_path( kwargs.get( 'external_service_type_config_file', 'external_service_types_conf.xml' ), self.root )
--- a/lib/galaxy/jobs/actions/post.py Fri Jun 03 10:16:20 2011 -0400
+++ b/lib/galaxy/jobs/actions/post.py Fri Jun 03 11:25:02 2011 -0400
@@ -1,5 +1,5 @@
-import logging, datetime, smtplib
-from email.MIMEText import MIMEText
+import logging, datetime
+from galaxy.util import send_mail
from galaxy.util.json import to_json_string
log = logging.getLogger( __name__ )
@@ -58,35 +58,17 @@
@classmethod
def execute(cls, app, sa_session, action, job, replacement_dict):
- smtp_server = app.config.smtp_server
if action.action_arguments and action.action_arguments.has_key('host'):
host = action.action_arguments['host']
else:
host = 'usegalaxy.org'
- if smtp_server is None:
- log.error("Mail is not configured for this galaxy instance. Workflow action aborting after logging mail to info.")
- frm = 'galaxy-noreply@%s' % host
- to = job.user.email
- outdata = ', '.join(ds.dataset.display_name() for ds in job.output_datasets)
- msg = MIMEText( "Your Galaxy job generating dataset '%s' is complete as of %s." % (outdata, datetime.datetime.now().strftime( "%I:%M" )))
- msg[ 'To' ] = to
- msg[ 'From' ] = frm
- msg[ 'Subject' ] = "Galaxy notification regarding history '%s'" % (job.history.name)
- log.info(msg)
- return
- # Build the email message
frm = 'galaxy-noreply@%s' % host
to = job.user.email
+ subject = "Galaxy workflow step notification '%s'" % (job.history.name)
outdata = ', '.join(ds.dataset.display_name() for ds in job.output_datasets)
- msg = MIMEText( "Your Galaxy job generating dataset '%s' is complete as of %s." % (outdata, datetime.datetime.now().strftime( "%I:%M" )))
- msg[ 'To' ] = to
- msg[ 'From' ] = frm
- msg[ 'Subject' ] = "Galaxy workflow step notification '%s'" % (job.history.name)
+ body = "Your Galaxy job generating dataset '%s' is complete as of %s." % (outdata, datetime.datetime.now().strftime( "%I:%M" ))
try:
- s = smtplib.SMTP()
- s.connect( smtp_server )
- s.sendmail( frm, [ to ], msg.as_string() )
- s.close()
+ send_mail( frm, to, subject, body, app.config )
except Exception, e:
log.error("EmailAction PJA Failed, exception: %s" % e)
--- a/lib/galaxy/model/__init__.py Fri Jun 03 10:16:20 2011 -0400
+++ b/lib/galaxy/model/__init__.py Fri Jun 03 11:25:02 2011 -0400
@@ -15,7 +15,7 @@
from galaxy.web.form_builder import *
from galaxy.model.item_attrs import UsesAnnotations, APIItem
from sqlalchemy.orm import object_session
-import os.path, os, errno, codecs, operator, smtplib, socket, pexpect, logging, time
+import os.path, os, errno, codecs, operator, socket, pexpect, logging, time
log = logging.getLogger( __name__ )
@@ -1803,12 +1803,8 @@
to = self.notification['email']
frm = 'galaxy-no-reply@' + host
subject = "Galaxy Sample Tracking notification: '%s' sequencing request" % self.name
- message = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s" % ( frm, ", ".join( to ), subject, body )
try:
- s = smtplib.SMTP()
- s.connect( trans.app.config.smtp_server )
- s.sendmail( frm, to, message )
- s.quit()
+ util.send_mail( frm, to, subject, body, trans.app.config )
comments = "Email notification sent to %s." % ", ".join( to ).strip().strip( ',' )
except Exception,e:
comments = "Email notification failed. (%s)" % str(e)
--- a/lib/galaxy/util/__init__.py Fri Jun 03 10:16:20 2011 -0400
+++ b/lib/galaxy/util/__init__.py Fri Jun 03 11:25:02 2011 -0400
@@ -2,7 +2,8 @@
Utility functions used systemwide.
"""
-import logging, threading, random, string, re, binascii, pickle, time, datetime, math, re, os, sys, tempfile, stat, grp
+import logging, threading, random, string, re, binascii, pickle, time, datetime, math, re, os, sys, tempfile, stat, grp, smtplib
+from email.MIMEText import MIMEText
# Older py compatibility
try:
@@ -540,6 +541,51 @@
return "%.1f %s" % (size, word)
return '??? bytes'
+def send_mail( frm, to, subject, body, config ):
+ """
+ Sends an email.
+ """
+ msg = MIMEText( body )
+ msg[ 'To' ] = to
+ msg[ 'From' ] = frm
+ msg[ 'Subject' ] = subject
+ if config.smtp_server is None:
+ log.error( "Mail is not configured for this Galaxy instance." )
+ log.info( msg )
+ return
+ s = smtplib.SMTP()
+ s.connect( config.smtp_server )
+ try:
+ s.starttls()
+ log.debug( 'Initiated SSL/TLS connection to SMTP server: %s' % config.smtp_server )
+ except RuntimeError, e:
+ log.warning( 'SSL/TLS support is not available to your Python interpreter: %s' % e )
+ except smtplib.SMTPHeloError, e:
+ log.error( "The server didn't reply properly to the HELO greeting: %s" % e )
+ s.close()
+ raise
+ except smtplib.SMTPException, e:
+ log.warning( 'The server does not support the STARTTLS extension: %s' % e )
+ if config.smtp_username and config.smtp_password:
+ try:
+ s.login( config.smtp_username, config.smtp_password )
+ except smtplib.SMTPHeloError, e:
+ log.error( "The server didn't reply properly to the HELO greeting: %s" % e )
+ s.close()
+ raise
+ except smtplib.SMTPAuthenticationError, e:
+ log.error( "The server didn't accept the username/password combination: %s" % e )
+ s.close()
+ raise
+ except smtplib.SMTPError, e:
+ log.error( "No suitable authentication method was found: %s" % e )
+ s.close()
+ raise
+ if isinstance( to, basestring ):
+ to = [ to ]
+ s.sendmail( frm, to, msg.as_string() )
+ s.quit()
+
galaxy_root_path = os.path.join(__path__[0], "..","..","..")
# The dbnames list is used in edit attributes and the upload tool
dbnames = read_dbnames( os.path.join( galaxy_root_path, "tool-data", "shared", "ucsc", "builds.txt" ) )
--- a/lib/galaxy/web/controllers/dataset.py Fri Jun 03 10:16:20 2011 -0400
+++ b/lib/galaxy/web/controllers/dataset.py Fri Jun 03 11:25:02 2011 -0400
@@ -1,4 +1,4 @@
-import logging, os, string, shutil, re, socket, mimetypes, smtplib, urllib, tempfile, zipfile, glob, sys
+import logging, os, string, shutil, re, socket, mimetypes, urllib, tempfile, zipfile, glob, sys
from galaxy.web.base.controller import *
from galaxy.web.framework.helpers import time_ago, iff, grids
@@ -10,7 +10,6 @@
from galaxy.model.item_attrs import *
from galaxy.model import LibraryDatasetDatasetAssociation, HistoryDatasetAssociation
-from email.MIMEText import MIMEText
import pkg_resources;
pkg_resources.require( "Paste" )
import paste.httpexceptions
@@ -174,7 +173,7 @@
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 )
+ body = string.Template( error_report_template ) \
.safe_substitute( host=host,
dataset_id=hda.dataset_id,
history_id=hda.history_id,
@@ -189,7 +188,7 @@
job_info=job.info,
job_traceback=job.traceback,
email=email,
- message=message ) )
+ message=message )
frm = to_address
# Check email a bit
email = email.strip()
@@ -198,15 +197,10 @@
to = to_address + ", " + email
else:
to = to_address
- msg[ 'To' ] = to
- msg[ 'From' ] = frm
- msg[ 'Subject' ] = "Galaxy tool error report from " + email
+ subject = "Galaxy tool error report from " + email
# Send it
try:
- s = smtplib.SMTP()
- s.connect( smtp_server )
- s.sendmail( frm, [ to ], msg.as_string() )
- s.close()
+ util.send_mail( frm, to, subject, body, trans.app.config )
return trans.show_ok_message( "Your error report has been sent" )
except Exception, e:
return trans.show_error_message( "An error occurred sending the report by email: %s" % str( e ) )
--- a/lib/galaxy/web/controllers/user.py Fri Jun 03 10:16:20 2011 -0400
+++ b/lib/galaxy/web/controllers/user.py Fri Jun 03 11:25:02 2011 -0400
@@ -5,9 +5,8 @@
from galaxy.web.base.controller import *
from galaxy.model.orm import *
from galaxy import util, model
-import logging, os, string, re, smtplib, socket, glob
+import logging, os, string, re, socket, glob
from random import choice
-from email.MIMEText import MIMEText
from galaxy.web.form_builder import *
from galaxy.util.json import from_json_string, to_json_string
from galaxy.web.framework.helpers import iff
@@ -560,15 +559,12 @@
if trans.app.config.smtp_server is None:
error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed because mail is not configured for this Galaxy instance."
else:
- msg = MIMEText( 'Join Mailing list.\n' )
- to = msg[ 'To' ] = trans.app.config.mailing_join_addr
- frm = msg[ 'From' ] = email
- msg[ 'Subject' ] = 'Join Mailing List'
+ body = 'Join Mailing list.\n'
+ to = trans.app.config.mailing_join_addr
+ frm = email
+ subject = 'Join Mailing List'
try:
- s = smtplib.SMTP()
- s.connect( trans.app.config.smtp_server )
- s.sendmail( frm, [ to ], msg.as_string() )
- s.close()
+ util.send_mail( frm, to, subject, body, trans.app.config )
except:
error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed."
if not error and not is_admin:
@@ -888,15 +884,12 @@
host = trans.request.host.split(':')[0]
if host == 'localhost':
host = socket.getfqdn()
- msg = MIMEText( 'Your password on %s has been reset to:\n\n %s\n' % ( host, new_pass ) )
- to = msg[ 'To' ] = email
- frm = msg[ 'From' ] = 'galaxy-no-reply@' + host
- msg[ 'Subject' ] = 'Galaxy Password Reset'
+ body = 'Your password on %s has been reset to:\n\n %s\n' % ( host, new_pass )
+ to = email
+ frm = 'galaxy-no-reply@' + host
+ subject = 'Galaxy Password Reset'
try:
- s = smtplib.SMTP()
- s.connect( trans.app.config.smtp_server )
- s.sendmail( frm, [ to ], msg.as_string() )
- s.close()
+ util.send_mail( frm, to, subject, body, trans.app.config )
reset_user.set_password_cleartext( new_pass )
trans.sa_session.add( reset_user )
trans.sa_session.flush()
--- a/universe_wsgi.ini.sample Fri Jun 03 10:16:20 2011 -0400
+++ b/universe_wsgi.ini.sample Fri Jun 03 11:25:02 2011 -0400
@@ -161,9 +161,16 @@
# Galaxy sends mail for various things: Subscribing users to the mailing list
# if they request it, emailing password resets, notification from the Galaxy
# Sample Tracking system, and reporting dataset errors. To do this, it needs
-# to send mail through an SMTP server, which you may define here.
+# to send mail through an SMTP server, which you may define here (host:port).
+# Galaxy will automatically try STARTTLS but will continue upon failure.
#smtp_server = None
+# If your SMTP server requires a username and password, you can provide them
+# here (password in cleartext here, but if your server supports STARTTLS it
+# will be sent over the network encrypted).
+#smtp_username = None
+#smtp_password = None
+
# On the user registration form, users may choose to join the mailing list.
# This is the address of the list they'll be subscribed to.
#mailing_join_addr = galaxy-user-join(a)bx.psu.edu
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: dan: Fixes for Implicit Datatype conversion and external display applications.
by Bitbucket 03 Jun '11
by Bitbucket 03 Jun '11
03 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/4c7437d5583c/
changeset: 4c7437d5583c
branches:
user: dan
date: 2011-06-03 16:16:20
summary: Fixes for Implicit Datatype conversion and external display applications.
affected #: 2 files (167 bytes)
--- a/lib/galaxy/datatypes/display_applications/parameters.py Thu Jun 02 17:36:38 2011 -0400
+++ b/lib/galaxy/datatypes/display_applications/parameters.py Fri Jun 03 10:16:20 2011 -0400
@@ -92,6 +92,8 @@
#find target ext
target_ext, converted_dataset = data.find_conversion_destination( self.formats, converter_safe = True )
if target_ext and not converted_dataset:
+ if isinstance( data, DisplayDataValueWrapper ):
+ data = data.value
assoc = trans.app.model.ImplicitlyConvertedDatasetAssociation( parent = data, file_type = target_ext, metadata_safe = False )
new_data = data.datatype.convert_dataset( trans, data, target_ext, return_output = True, visible = False ).values()[0]
new_data.hid = data.hid
--- a/lib/galaxy/model/__init__.py Thu Jun 02 17:36:38 2011 -0400
+++ b/lib/galaxy/model/__init__.py Fri Jun 03 10:16:20 2011 -0400
@@ -1353,7 +1353,7 @@
elif isinstance(parent, LibraryDatasetDatasetAssociation):
self.parent_ldda = parent
else:
- raise AttributeError
+ raise AttributeError, 'Unknown dataset type provided for parent: %s' % type( parent )
self.type = file_type
self.deleted = deleted
self.purged = purged
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new changesets in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/f197067c32ef/
changeset: f197067c32ef
branches:
user: natefoo
date: 2011-06-02 22:38:19
summary: Backed out changeset 2f84c42a548a. Unbreaks all checkboxes being checked by default, rebreaks default="true".
affected #: 1 file (103 bytes)
--- a/lib/galaxy/web/form_builder.py Tue May 24 05:33:07 2011 -0400
+++ b/lib/galaxy/web/form_builder.py Thu Jun 02 16:38:19 2011 -0400
@@ -4,7 +4,7 @@
import logging, sys, os, time
from cgi import escape
-from galaxy.util import restore_text, relpath, nice_size, string_as_bool
+from galaxy.util import restore_text, relpath, nice_size
from galaxy.web import url_for
log = logging.getLogger(__name__)
@@ -112,8 +112,6 @@
# above for clarification. Basically, if value is not True, then it will always be a list with
# 2 input fields ( a checkbox and a hidden field ) if the checkbox is checked. If it is not
# checked, then value will be only the hidden field.
- if isinstance( value, basestring ):
- return string_as_bool( value )
return isinstance( value, list ) and len( value ) == 2
def set_checked(self, value):
if isinstance( value, basestring ):
http://bitbucket.org/galaxy/galaxy-central/changeset/7b1c74229393/
changeset: 7b1c74229393
branches:
user: natefoo
date: 2011-06-02 22:38:34
summary: merge backout
affected #: 1 file (103 bytes)
--- a/lib/galaxy/web/form_builder.py Thu Jun 02 16:24:43 2011 -0400
+++ b/lib/galaxy/web/form_builder.py Thu Jun 02 16:38:34 2011 -0400
@@ -4,7 +4,7 @@
import logging, sys, os, time
from cgi import escape
-from galaxy.util import restore_text, relpath, nice_size, string_as_bool
+from galaxy.util import restore_text, relpath, nice_size
from galaxy.web import url_for
log = logging.getLogger(__name__)
@@ -112,8 +112,6 @@
# above for clarification. Basically, if value is not True, then it will always be a list with
# 2 input fields ( a checkbox and a hidden field ) if the checkbox is checked. If it is not
# checked, then value will be only the hidden field.
- if isinstance( value, basestring ):
- return string_as_bool( value )
return isinstance( value, list ) and len( value ) == 2
def set_checked(self, value):
if isinstance( value, basestring ):
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

02 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/347df1c9f9b0/
changeset: 347df1c9f9b0
branches:
user: greg
date: 2011-06-02 22:24:43
summary: Delete community_datatypes_conf.xml.sample
affected #: 1 file (0 bytes)
--- a/community_datatypes_conf.xml.sample Thu Jun 02 16:16:56 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-<?xml version="1.0"?>
-<datatypes>
- <registration>
- <datatype extension="tool" type="galaxy.webapps.community.datatypes:Tool" model="galaxy.webapps.community.model:Tool"/>
- <datatype extension="toolsuite" type="galaxy.webapps.community.datatypes:ToolSuite" model="galaxy.webapps.community.model:Tool"/>
- </registration>
-</datatypes>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: greg: Add baseline support for translating special chars to html escape codes for correct html display. Fixes issue # 564.
by Bitbucket 02 Jun '11
by Bitbucket 02 Jun '11
02 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/02df5336a7b2/
changeset: 02df5336a7b2
branches:
user: greg
date: 2011-06-02 22:16:56
summary: Add baseline support for translating special chars to html escape codes for correct html display. Fixes issue # 564.
affected #: 1 file (750 bytes)
--- a/lib/galaxy/webapps/community/controllers/repository.py Thu Jun 02 15:18:35 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/repository.py Thu Jun 02 16:16:56 2011 -0400
@@ -14,7 +14,12 @@
log = logging.getLogger( __name__ )
VALID_REPOSITORYNAME_RE = re.compile( "^[a-z0-9\_]+$" )
-
+# Characters that are valid
+VALID_CHARS = set( string.letters + string.digits )
+# Characters that must be html escaped
+MAPPED_CHARS = { '>' :'>',
+ '<' :'<' }
+
class CategoryListGrid( grids.Grid ):
# TODO rename this class to be categoryListGrid when we eliminate all the tools stuff.
class NameColumn( grids.TextColumn ):
@@ -167,7 +172,18 @@
repository_list_grid = RepositoryListGrid()
category_list_grid = CategoryListGrid()
-
+
+ # TODO: These translations are costly, so figure out a better way...
+ def from_html_escaped( self, text ):
+ """Restores sanitized text"""
+ for key, value in MAPPED_CHARS.items():
+ text = text.replace( value, key )
+ return text
+ def to_html_escape_code( self, text ):
+ """Restricts the characters that are allowed in a text"""
+ for key, value in MAPPED_CHARS.items():
+ text = text.replace( key, value )
+ return text
@web.expose
def index( self, trans, **kwd ):
params = util.Params( kwd )
@@ -564,7 +580,7 @@
for diff in patch.diff( repo, node1=ctx_parent.node(), node2=ctx.node() ):
if not util.is_multi_byte( diff ) and not is_binary( diff ):
# TODO: is there a better way?
- diffs.append( diff )
+ diffs.append( self.to_html_escape_code( diff ) )
else:
fixed_diff = diff.split( '\n' )[0] + '\nFile contains non-ascii characters that cannot be displayed\n'
diffs.append( fixed_diff )
@@ -679,6 +695,7 @@
output = pexpect.run( cmd,
events={ pexpect.TIMEOUT : print_ticks },
timeout=10 )
+ output = self.to_html_escape_code( output )
return unicode( output.replace( '\r\n', '<br/>' ).replace( ' ', ' ' ) )
@web.expose
def help( self, trans, **kwd ):
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: greg: Eliminate all suport for tool / tool suite archives from the tool shed. Yikes!
by Bitbucket 02 Jun '11
by Bitbucket 02 Jun '11
02 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/b02edf5334bf/
changeset: b02edf5334bf
branches:
user: greg
date: 2011-06-02 21:18:35
summary: Eliminate all suport for tool / tool suite archives from the tool shed. Yikes!
affected #: 25 files (61.6 KB)
--- a/community_wsgi.ini.sample Thu Jun 02 14:18:34 2011 -0400
+++ b/community_wsgi.ini.sample Thu Jun 02 15:18:35 2011 -0400
@@ -12,9 +12,6 @@
[app:main]
-# Enable next-gen tool shed features
-#enable_next_gen_tool_shed = True
-
# Specifies the factory for the universe WSGI application
paste.app_factory = galaxy.webapps.community.buildapp:app_factory
log_level = DEBUG
--- a/lib/galaxy/web/base/controller.py Thu Jun 02 14:18:34 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Thu Jun 02 15:18:35 2011 -0400
@@ -2026,16 +2026,6 @@
**kwd ) )
elif operation == "manage roles and groups":
return self.manage_roles_and_groups_for_user( trans, **kwd )
- elif operation == "tools_by_user":
- # This option is called via the ToolsColumn link in a grid subclass,
- # so we need to add user_id to kwd since id in the subclass is tool.id,
- # and update the current sort filter, using the grid subclass's default
- # sort filter instead of this class's.
- kwd[ 'user_id' ] = kwd[ 'id' ]
- kwd[ 'sort' ] = 'name'
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='browse_tools',
- **kwd ) )
# Render the list view
return self.user_list_grid( trans, **kwd )
@web.expose
--- a/lib/galaxy/webapps/community/app.py Thu Jun 02 14:18:34 2011 -0400
+++ b/lib/galaxy/webapps/community/app.py Thu Jun 02 15:18:35 2011 -0400
@@ -11,14 +11,6 @@
self.config = config.Configuration( **kwargs )
self.config.check()
config.configure_logging( self.config )
- if self.config.enable_next_gen_tool_shed:
- # We don't need a datatypes_registry since we have no datatypes
- pass
- else:
- import galaxy.webapps.community.datatypes
- # Set up datatypes registry
- self.datatypes_registry = galaxy.webapps.community.datatypes.Registry( self.config.root, self.config.datatypes_config )
- galaxy.model.set_datatypes_registry( self.datatypes_registry )
# Determine the database url
if self.config.database_connection:
db_url = self.config.database_connection
@@ -29,8 +21,7 @@
create_or_verify_database( db_url, self.config.database_engine_options )
# Setup the database engine and ORM
from galaxy.webapps.community.model import mapping
- self.model = mapping.init( self.config.enable_next_gen_tool_shed,
- self.config.file_path,
+ self.model = mapping.init( self.config.file_path,
db_url,
self.config.database_engine_options )
# Security helper
--- a/lib/galaxy/webapps/community/buildapp.py Thu Jun 02 14:18:34 2011 -0400
+++ b/lib/galaxy/webapps/community/buildapp.py Thu Jun 02 15:18:35 2011 -0400
@@ -31,12 +31,6 @@
controller_dir = galaxy.webapps.community.controllers.__path__[0]
for fname in os.listdir( controller_dir ):
if not fname.startswith( "_" ) and fname.endswith( ".py" ):
- if app.config.enable_next_gen_tool_shed and fname.startswith( 'tool_upload' ):
- # The tool_upload controller is for the old version of the tool shed
- continue
- if not app.config.enable_next_gen_tool_shed and fname.startswith( 'upload' ):
- # The upload controller is for the next gen tool shed
- continue
name = fname[:-3]
module_name = "galaxy.webapps.community.controllers." + name
module = __import__( module_name )
@@ -81,11 +75,8 @@
webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxycommunitysession' )
add_controllers( webapp, app )
webapp.add_route( '/:controller/:action', action='index' )
- if app.config.enable_next_gen_tool_shed:
- webapp.add_route( '/:action', controller='repository', action='index' )
- webapp.add_route( '/repos/*path_info', controller='hg', action='handle_request', path_info='/' )
- else:
- webapp.add_route( '/:action', controller='tool', action='index' )
+ webapp.add_route( '/:action', controller='repository', action='index' )
+ webapp.add_route( '/repos/*path_info', controller='hg', action='handle_request', path_info='/' )
webapp.finalize_config()
# Wrap the webapp in some useful middleware
if kwargs.get( 'middleware', True ):
--- a/lib/galaxy/webapps/community/config.py Thu Jun 02 14:18:34 2011 -0400
+++ b/lib/galaxy/webapps/community/config.py Thu Jun 02 15:18:35 2011 -0400
@@ -47,7 +47,6 @@
self.require_login = string_as_bool( kwargs.get( "require_login", "False" ) )
self.allow_user_creation = string_as_bool( kwargs.get( "allow_user_creation", "True" ) )
self.enable_openid = string_as_bool( kwargs.get( 'enable_openid', False ) )
- self.enable_next_gen_tool_shed = string_as_bool( kwargs.get( 'enable_next_gen_tool_shed', False ) )
self.template_path = resolve_path( kwargs.get( "template_path", "templates" ), self.root )
self.template_cache = resolve_path( kwargs.get( "template_cache_path", "database/compiled_templates/community" ), self.root )
self.admin_users = kwargs.get( "admin_users", "" )
--- a/lib/galaxy/webapps/community/controllers/admin.py Thu Jun 02 14:18:34 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/admin.py Thu Jun 02 15:18:35 2011 -0400
@@ -2,14 +2,14 @@
from galaxy.webapps.community import model
from galaxy.model.orm import *
from galaxy.web.framework.helpers import time_ago, iff, grids
-from common import ToolListGrid, CategoryListGrid, get_category, get_event, get_tool, get_versions
-from repository import RepositoryListGrid, RepositoryCategoryListGrid
+from common import get_category, get_repository
+from repository import RepositoryListGrid, CategoryListGrid
import logging
log = logging.getLogger( __name__ )
class UserListGrid( grids.Grid ):
# TODO: move this to an admin_common controller since it is virtually the same
- # in the galaxy webapp. NOTE the additional ToolsColumn in this grid though...
+ # in the galaxy webapp.
class UserLoginColumn( grids.TextColumn ):
def get_value( self, trans, grid, user ):
return user.email
@@ -282,58 +282,6 @@
preserve_state = False
use_paging = True
-class AdminToolListGrid( ToolListGrid ):
- class StateColumn( grids.TextColumn ):
- def get_value( self, trans, grid, tool ):
- state = tool.state
- if state == 'approved':
- state_color = 'ok'
- elif state == 'rejected':
- state_color = 'error'
- elif state == 'archived':
- state_color = 'upload'
- else:
- state_color = state
- return '<div class="count-box state-color-%s">%s</div>' % ( state_color, state )
- class ToolStateColumn( grids.StateColumn ):
- def filter( self, trans, user, query, column_filter ):
- """Modify query to filter by state."""
- if column_filter == "All":
- pass
- elif column_filter in [ v for k, v in self.model_class.states.items() ]:
- # Get all of the latest ToolEventAssociation ids
- tea_ids = [ tea_id_tup[0] for tea_id_tup in trans.sa_session.query( func.max( model.ToolEventAssociation.table.c.id ) ) \
- .group_by( model.ToolEventAssociation.table.c.tool_id ) ]
- # Get all of the Event ids associated with the latest ToolEventAssociation ids
- event_ids = [ event_id_tup[0] for event_id_tup in trans.sa_session.query( model.ToolEventAssociation.table.c.event_id ) \
- .filter( model.ToolEventAssociation.table.c.id.in_( tea_ids ) ) ]
- # Filter our query by state and event ids
- return query.filter( and_( model.Event.table.c.state == column_filter,
- model.Event.table.c.id.in_( event_ids ) ) )
- return query
-
- columns = [ col for col in ToolListGrid.columns ]
- columns.append(
- StateColumn( "Status",
- model_class=model.Tool,
- link=( lambda item: dict( operation="tools_by_state", id=item.id, webapp="community" ) ),
- attach_popup=False ),
- )
- columns.append(
- # Columns that are valid for filtering but are not visible.
- ToolStateColumn( "State",
- key="state",
- model_class=model.Tool,
- visible=False,
- filterable="advanced" )
- )
- operations = [
- grids.GridOperation( "Edit information",
- condition=( lambda item: not item.deleted ),
- allow_multiple=False,
- url_args=dict( controller="common", action="edit_tool", cntrller="admin", webapp="community" ) )
- ]
-
class AdminCategoryListGrid( CategoryListGrid ):
# Override standard filters
standard_filters = [
@@ -374,83 +322,20 @@
role_list_grid = RoleListGrid()
group_list_grid = GroupListGrid()
manage_category_list_grid = ManageCategoryListGrid()
- tool_category_list_grid = AdminCategoryListGrid()
- tool_list_grid = AdminToolListGrid()
repository_list_grid = RepositoryListGrid()
- repository_category_list_grid = RepositoryCategoryListGrid()
+ category_list_grid = CategoryListGrid()
@web.expose
@web.require_admin
- def browse_tools( self, trans, **kwd ):
- # We add params to the keyword dict in this method in order to rename the param
- # with an "f-" prefix, simulating filtering by clicking a search link. We have
- # to take this approach because the "-" character is illegal in HTTP requests.
- if 'operation' in kwd:
- operation = kwd['operation'].lower()
- if operation == "edit_tool":
- return trans.response.send_redirect( web.url_for( controller='common',
- action='edit_tool',
- cntrller='admin',
- **kwd ) )
- elif operation == "view_tool":
- return trans.response.send_redirect( web.url_for( controller='common',
- action='view_tool',
- cntrller='admin',
- **kwd ) )
- elif operation == 'tool_history':
- return trans.response.send_redirect( web.url_for( controller='common',
- cntrller='admin',
- action='events',
- **kwd ) )
- elif operation == "tools_by_user":
- # Eliminate the current filters if any exist.
- for k, v in kwd.items():
- if k.startswith( 'f-' ):
- del kwd[ k ]
- if 'user_id' in kwd:
- user = get_user( trans, kwd[ 'user_id' ] )
- kwd[ 'f-email' ] = user.email
- del kwd[ 'user_id' ]
- else:
- # The received id is the tool id, so we need to get the id of the user
- # that uploaded the tool.
- tool_id = kwd.get( 'id', None )
- tool = get_tool( trans, tool_id )
- kwd[ 'f-email' ] = tool.user.email
- elif operation == "tools_by_state":
- # Eliminate the current filters if any exist.
- for k, v in kwd.items():
- if k.startswith( 'f-' ):
- del kwd[ k ]
- if 'state' in kwd:
- # Called from the Admin menu
- kwd[ 'f-state' ] = kwd[ 'state' ]
- else:
- # Called from the ToolStateColumn link
- tool_id = kwd.get( 'id', None )
- tool = get_tool( trans, tool_id )
- kwd[ 'f-state' ] = tool.state
- elif operation == "tools_by_category":
- # Eliminate the current filters if any exist.
- for k, v in kwd.items():
- if k.startswith( 'f-' ):
- del kwd[ k ]
- category_id = kwd.get( 'id', None )
- category = get_category( trans, category_id )
- kwd[ 'f-Category.name' ] = category.name
- # Render the list view
- return self.tool_list_grid( trans, **kwd )
- @web.expose
- @web.require_admin
def browse_repositories( self, trans, **kwd ):
# We add params to the keyword dict in this method in order to rename the param
# with an "f-" prefix, simulating filtering by clicking a search link. We have
# to take this approach because the "-" character is illegal in HTTP requests.
if 'operation' in kwd:
operation = kwd['operation'].lower()
- if operation == "view_repository":
+ if operation == "view_or_manage_repository":
return trans.response.send_redirect( web.url_for( controller='repository',
- action='view_repository',
+ action='browse_repositories',
**kwd ) )
elif operation == "edit_repository":
return trans.response.send_redirect( web.url_for( controller='repository',
@@ -485,29 +370,16 @@
@web.require_admin
def browse_categories( self, trans, **kwd ):
if 'operation' in kwd:
- operation = kwd['operation'].lower()
- if trans.app.config.enable_next_gen_tool_shed:
- if operation in [ "repositories_by_category", "repositories_by_user" ]:
- # Eliminate the current filters if any exist.
- for k, v in kwd.items():
- if k.startswith( 'f-' ):
- del kwd[ k ]
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='browse_repositories',
- **kwd ) )
- else:
- if operation in [ "tools_by_category", "tools_by_state", "tools_by_user" ]:
- # Eliminate the current filters if any exist.
- for k, v in kwd.items():
- if k.startswith( 'f-' ):
- del kwd[ k ]
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='browse_tools',
- **kwd ) )
- if trans.app.config.enable_next_gen_tool_shed:
- return self.repository_category_list_grid( trans, **kwd )
- else:
- return self.tool_category_list_grid( trans, **kwd )
+ operation = kwd[ 'operation' ].lower()
+ if operation in [ "repositories_by_category", "repositories_by_user" ]:
+ # Eliminate the current filters if any exist.
+ for k, v in kwd.items():
+ if k.startswith( 'f-' ):
+ del kwd[ k ]
+ return trans.response.send_redirect( web.url_for( controller='admin',
+ action='browse_repositories',
+ **kwd ) )
+ return self.category_list_grid( trans, **kwd )
@web.expose
@web.require_admin
def manage_categories( self, trans, **kwd ):
@@ -573,140 +445,6 @@
status=status )
@web.expose
@web.require_admin
- def set_tool_state( self, trans, state, **kwd ):
- params = util.Params( kwd )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- comments = util.restore_text( params.get( 'comments', '' ) )
- id = params.get( 'id', None )
- if not id:
- message = "No tool id received for setting status"
- status = 'error'
- else:
- tool = get_tool( trans, id )
- if state == trans.app.model.Tool.states.APPROVED:
- # If we're approving a tool, all previously approved versions must be set to archived
- for version in get_versions( tool ):
- # TODO: get latest approved version instead of all versions
- if version != tool and version.is_approved:
- # Create an event with state ARCHIVED for the previously approved version of this tool
- self.__create_tool_event( trans,
- version,
- trans.app.model.Tool.states.ARCHIVED )
- # Create an event with state APPROVED for this tool
- self.__create_tool_event( trans, tool, state, comments )
- elif state == trans.app.model.Tool.states.REJECTED:
- # If we're rejecting a tool, comments about why are necessary.
- return trans.fill_template( '/webapps/community/admin/reject_tool.mako',
- tool=tool,
- cntrller='admin' )
- message = "State of tool '%s' is now %s" % ( tool.name, state )
- trans.response.send_redirect( web.url_for( controller='admin',
- action='browse_tools',
- message=message,
- status=status ) )
- @web.expose
- @web.require_admin
- def reject_tool( self, trans, **kwd ):
- params = util.Params( kwd )
- if params.get( 'cancel_reject_button', False ):
- # Fix up the keyword dict to include params to view the current tool
- # since that is the page from which we originated.
- del kwd[ 'cancel_reject_button' ]
- del kwd[ 'comments' ]
- kwd[ 'webapp' ] = 'community'
- kwd[ 'operation' ] = 'view_tool'
- message = 'Tool rejection cancelled'
- status = 'done'
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='browse_tools',
- message=message,
- status=status,
- **kwd ) )
- id = params.get( 'id', None )
- if not id:
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- message='No tool id received for rejecting',
- status='error' ) )
- tool = get_tool( trans, id )
- if not trans.app.security_agent.can_approve_or_reject( trans.user, trans.user_is_admin(), 'admin', tool ):
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='browse_tools',
- message='You are not allowed to reject this tool',
- status='error' ) )
- # Comments are required when rejecting a tool.
- comments = util.restore_text( params.get( 'comments', '' ) )
- if not comments:
- message = 'The reason for rejection is required when rejecting a tool.'
- return trans.fill_template( '/webapps/community/admin/reject_tool.mako',
- tool=tool,
- cntrller='admin',
- message=message,
- status='error' )
- # Create an event with state REJECTED for this tool
- self.__create_tool_event( trans, tool, trans.app.model.Tool.states.REJECTED, comments )
- message = 'The tool "%s" has been rejected.' % tool.name
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='browse_tools',
- operation='tools_by_state',
- state='rejected',
- message=message,
- status='done' ) )
- def __create_tool_event( self, trans, tool, state, comments='' ):
- event = trans.model.Event( state, comments )
- # Flush so we can get an id
- trans.sa_session.add( event )
- trans.sa_session.flush()
- tea = trans.model.ToolEventAssociation( tool, event )
- trans.sa_session.add( tea )
- trans.sa_session.flush()
- @web.expose
- @web.require_admin
- def purge_tool( self, trans, **kwd ):
- # This method completely removes a tool record and all associated foreign key rows
- # from the database, so it must be used carefully.
- # This method should only be called for a tool that has previously been deleted.
- # Purging a deleted tool deletes all of the following from the database:
- # - ToolCategoryAssociations
- # - ToolEventAssociations and associated Events
- # TODO: when we add tagging for tools, we'll have to purge them as well
- params = util.Params( kwd )
- id = kwd.get( 'id', None )
- if not id:
- message = "No tool ids received for purging"
- trans.response.send_redirect( web.url_for( controller='admin',
- action='browse_tools',
- message=util.sanitize_text( message ),
- status='error' ) )
- ids = util.listify( id )
- message = "Purged %d tools: " % len( ids )
- for tool_id in ids:
- tool = get_tool( trans, tool_id )
- message += " %s " % tool.name
- if not tool.deleted:
- message = "Tool '%s' has not been deleted, so it cannot be purged." % tool.name
- trans.response.send_redirect( web.url_for( controller='admin',
- action='browse_tools',
- message=util.sanitize_text( message ),
- status='error' ) )
- # Delete ToolCategoryAssociations
- for tca in tool.categories:
- trans.sa_session.delete( tca )
- # Delete ToolEventAssociations and associated events
- for tea in tool.events:
- event = tea.event
- trans.sa_session.delete( event )
- trans.sa_session.delete( tea )
- # Delete the tool
- trans.sa_session.delete( tool )
- trans.sa_session.flush()
- trans.response.send_redirect( web.url_for( controller='admin',
- action='browse_tools',
- message=util.sanitize_text( message ),
- status='done' ) )
- @web.expose
- @web.require_admin
def edit_category( self, trans, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
@@ -804,10 +542,7 @@
def purge_category( self, trans, **kwd ):
# This method should only be called for a Category that has previously been deleted.
# Purging a deleted Category deletes all of the following from the database:
- # If trans.app.config.enable_next_gen_tool_shed:
# - RepoitoryCategoryAssociations where category_id == Category.id
- # Otherwise:
- # - ToolCategoryAssociations where category_id == Category.id
params = util.Params( kwd )
id = kwd.get( 'id', None )
if not id:
@@ -826,14 +561,9 @@
action='manage_categories',
message=util.sanitize_text( message ),
status='error' ) )
- if trans.app.config.enable_next_gen_tool_shed:
- # Delete RepositoryCategoryAssociations
- for rca in category.repositories:
- trans.sa_session.delete( rca )
- else:
- # Delete ToolCategoryAssociations
- for tca in category.tools:
- trans.sa_session.delete( tca )
+ # Delete RepositoryCategoryAssociations
+ for rca in category.repositories:
+ trans.sa_session.delete( rca )
trans.sa_session.flush()
message += " %s " % category.name
trans.response.send_redirect( web.url_for( controller='admin',
--- a/lib/galaxy/webapps/community/controllers/common.py Thu Jun 02 14:18:34 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/common.py Thu Jun 02 15:18:35 2011 -0400
@@ -34,508 +34,8 @@
trans.sa_session.flush()
return item_rating
-class ToolListGrid( grids.Grid ):
- class NameColumn( grids.TextColumn ):
- def get_value( self, trans, grid, tool ):
- return tool.name
- class TypeColumn( grids.BooleanColumn ):
- def get_value( self, trans, grid, tool ):
- if tool.is_suite:
- return 'Suite'
- return 'Tool'
- class VersionColumn( grids.TextColumn ):
- def get_value( self, trans, grid, tool ):
- return tool.version
- class DescriptionColumn( grids.TextColumn ):
- def get_value( self, trans, grid, tool ):
- return tool.description
- class CategoryColumn( grids.TextColumn ):
- def get_value( self, trans, grid, tool ):
- rval = '<ul>'
- if tool.categories:
- for tca in tool.categories:
- rval += '<li><a href="browse_tools?operation=tools_by_category&id=%s&webapp=community">%s</a></li>' \
- % ( trans.security.encode_id( tca.category.id ), tca.category.name )
- else:
- rval += '<li>not set</li>'
- rval += '</ul>'
- return rval
- class ToolCategoryColumn( grids.GridColumn ):
- def filter( self, trans, user, query, column_filter ):
- """Modify query to filter by category."""
- if column_filter == "All":
- pass
- return query.filter( model.Category.name == column_filter )
- class UserColumn( grids.TextColumn ):
- def get_value( self, trans, grid, tool ):
- if tool.user:
- return tool.user.username
- return 'no user'
- class EmailColumn( grids.TextColumn ):
- def filter( self, trans, user, query, column_filter ):
- if column_filter == 'All':
- return query
- return query.filter( and_( model.Tool.table.c.user_id == model.User.table.c.id,
- model.User.table.c.email == column_filter ) )
- # Grid definition
- title = "Tools"
- model_class = model.Tool
- template='/webapps/community/tool/grid.mako'
- default_sort_key = "name"
- columns = [
- NameColumn( "Name",
- key="Tool.name",
- link=( lambda item: dict( operation="view_tool", id=item.id, webapp="community" ) ),
- attach_popup=False ),
- DescriptionColumn( "Description",
- key="description",
- attach_popup=False ),
- VersionColumn( "Version",
- key="version",
- attach_popup=False,
- filterable="advanced" ),
- CategoryColumn( "Category",
- model_class=model.Category,
- key="Category.name",
- attach_popup=False ),
- UserColumn( "Uploaded By",
- model_class=model.User,
- link=( lambda item: dict( operation="tools_by_user", id=item.id, webapp="community" ) ),
- attach_popup=False,
- key="username" ),
- TypeColumn( "Type",
- key="suite",
- attach_popup=False ),
- grids.CommunityRatingColumn( "Average Rating",
- key="rating" ),
- # Columns that are valid for filtering but are not visible.
- EmailColumn( "Email",
- model_class=model.User,
- key="email",
- visible=False ),
- ToolCategoryColumn( "Category",
- model_class=model.Category,
- key="Category.name",
- visible=False )
- ]
- columns.append( grids.MulticolFilterColumn( "Search tool name, description, version",
- cols_to_filter=[ columns[0], columns[1], columns[2] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
- operations = []
- standard_filters = []
- default_filter = {}
- num_rows_per_page = 50
- preserve_state = False
- use_paging = True
- def build_initial_query( self, trans, **kwd ):
- return trans.sa_session.query( self.model_class ) \
- .join( model.User.table ) \
- .join( model.ToolEventAssociation.table ) \
- .join( model.Event.table ) \
- .outerjoin( model.ToolCategoryAssociation.table ) \
- .outerjoin( model.Category.table )
-
-class CategoryListGrid( grids.Grid ):
- class NameColumn( grids.TextColumn ):
- def get_value( self, trans, grid, category ):
- return category.name
- class DescriptionColumn( grids.TextColumn ):
- def get_value( self, trans, grid, category ):
- return category.description
- class ToolsColumn( grids.TextColumn ):
- def get_value( self, trans, grid, category ):
- if category.tools:
- viewable_tools = 0
- for tca in category.tools:
- viewable_tools += 1
- return viewable_tools
- return 0
-
- # Grid definition
- webapp = "community"
- title = "Categories"
- model_class = model.Category
- template='/webapps/community/category/grid.mako'
- default_sort_key = "name"
- columns = [
- NameColumn( "Name",
- key="name",
- link=( lambda item: dict( operation="tools_by_category", id=item.id, webapp="community" ) ),
- attach_popup=False,
- filterable="advanced" ),
- DescriptionColumn( "Description",
- key="description",
- attach_popup=False,
- filterable="advanced" ),
- # Columns that are valid for filtering but are not visible.
- grids.DeletedColumn( "Deleted",
- key="deleted",
- visible=False,
- filterable="advanced" ),
- ToolsColumn( "Tools",
- model_class=model.Tool,
- attach_popup=False )
- ]
- columns.append( grids.MulticolFilterColumn( "Search category name, description",
- cols_to_filter=[ columns[0], columns[1] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
-
- # Override these
- global_actions = []
- operations = []
- standard_filters = []
- num_rows_per_page = 50
- preserve_state = False
- use_paging = True
-
-class CommonController( BaseController, ItemRatings ):
- @web.expose
- def edit_tool( self, trans, cntrller, **kwd ):
- params = util.Params( kwd )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- id = params.get( 'id', None )
- if not id:
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- cntrller=cntrller,
- message='Select a tool to edit',
- status='error' ) )
- tool = get_tool( trans, id )
- can_edit = trans.app.security_agent.can_edit( trans.user, trans.user_is_admin(), cntrller, tool )
- if not can_edit:
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- cntrller=cntrller,
- message='You are not allowed to edit this tool',
- status='error' ) )
- if params.get( 'edit_tool_button', False ):
- if params.get( 'in_categories', False ):
- in_categories = [ trans.sa_session.query( trans.app.model.Category ).get( x ) for x in util.listify( params.in_categories ) ]
- trans.app.security_agent.set_entity_category_associations( tools=[ tool ], categories=in_categories )
- else:
- # There must not be any categories associated with the tool
- trans.app.security_agent.set_entity_category_associations( tools=[ tool ], categories=[] )
- user_description = util.restore_text( params.get( 'user_description', '' ) )
- if user_description:
- tool.user_description = user_description
- else:
- tool.user_description = ''
- trans.sa_session.add( tool )
- trans.sa_session.flush()
- message = "Tool '%s' description and category associations have been saved" % tool.name
- return trans.response.send_redirect( web.url_for( controller='common',
- action='edit_tool',
- cntrller=cntrller,
- id=id,
- message=message,
- status='done' ) )
- elif params.get( 'approval_button', False ):
- user_description = util.restore_text( params.get( 'user_description', '' ) )
- if user_description:
- tool.user_description = user_description
- if params.get( 'in_categories', False ):
- in_categories = [ trans.sa_session.query( trans.app.model.Category ).get( x ) for x in util.listify( params.in_categories ) ]
- trans.app.security_agent.set_entity_category_associations( tools=[ tool ], categories=in_categories )
- else:
- # There must not be any categories associated with the tool
- trans.app.security_agent.set_entity_category_associations( tools=[ tool ], categories=[] )
- trans.sa_session.add( tool )
- trans.sa_session.flush()
- # Move the state from NEW to WAITING
- event = trans.app.model.Event( state=trans.app.model.Tool.states.WAITING )
- tea = trans.app.model.ToolEventAssociation( tool, event )
- trans.sa_session.add_all( ( event, tea ) )
- trans.sa_session.flush()
- message = "Tool '%s' has been submitted for approval and can no longer be modified" % ( tool.name )
- return trans.response.send_redirect( web.url_for( controller='common',
- action='view_tool',
- cntrller=cntrller,
- id=id,
- message=message,
- status='done' ) )
- else:
- # The user_description field is required when submitting for approval
- message = 'A user description is required prior to approval.'
- status = 'error'
- in_categories = []
- out_categories = []
- for category in get_categories( trans ):
- if category in [ x.category for x in tool.categories ]:
- in_categories.append( ( category.id, category.name ) )
- else:
- out_categories.append( ( category.id, category.name ) )
- if tool.is_rejected:
- # Include the comments regarding the reason for rejection
- reason_for_rejection = tool.latest_event.comment
- else:
- reason_for_rejection = ''
- can_approve_or_reject = trans.app.security_agent.can_approve_or_reject( trans.user, trans.user_is_admin(), cntrller, tool )
- can_delete = trans.app.security_agent.can_delete( trans.user, trans.user_is_admin(), cntrller, tool )
- can_download = trans.app.security_agent.can_download( trans.user, trans.user_is_admin(), cntrller, tool )
- can_purge = trans.app.security_agent.can_purge( trans.user, trans.user_is_admin(), cntrller )
- can_upload_new_version = trans.app.security_agent.can_upload_new_version( trans.user, tool )
- can_view = trans.app.security_agent.can_view( trans.user, trans.user_is_admin(), cntrller, tool )
- return trans.fill_template( '/webapps/community/tool/edit_tool.mako',
- cntrller=cntrller,
- tool=tool,
- id=id,
- in_categories=in_categories,
- out_categories=out_categories,
- can_approve_or_reject=can_approve_or_reject,
- can_delete=can_delete,
- can_download=can_download,
- can_edit=can_edit,
- can_purge=can_purge,
- can_upload_new_version=can_upload_new_version,
- can_view=can_view,
- reason_for_rejection=reason_for_rejection,
- message=message,
- status=status )
- @web.expose
- def view_tool( self, trans, cntrller, **kwd ):
- params = util.Params( kwd )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- id = params.get( 'id', None )
- if not id:
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- cntrller=cntrller,
- message='Select a tool to view',
- status='error' ) )
- tool = get_tool( trans, id )
- can_view = trans.app.security_agent.can_view( trans.user, trans.user_is_admin(), cntrller, tool )
- if not can_view:
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- cntrller=cntrller,
- message='You are not allowed to view this tool',
- status='error' ) )
- avg_rating, num_ratings = self.get_ave_item_rating_data( trans.sa_session, tool, webapp_model=trans.model )
- can_approve_or_reject = trans.app.security_agent.can_approve_or_reject( trans.user, trans.user_is_admin(), cntrller, tool )
- can_delete = trans.app.security_agent.can_delete( trans.user, trans.user_is_admin(), cntrller, tool )
- can_download = trans.app.security_agent.can_download( trans.user, trans.user_is_admin(), cntrller, tool )
- can_edit = trans.app.security_agent.can_edit( trans.user, trans.user_is_admin(), cntrller, tool )
- can_purge = trans.app.security_agent.can_purge( trans.user, trans.user_is_admin(), cntrller )
- can_rate = trans.app.security_agent.can_rate( trans.user, trans.user_is_admin(), cntrller, tool )
- can_upload_new_version = trans.app.security_agent.can_upload_new_version( trans.user, tool )
- categories = [ tca.category for tca in tool.categories ]
- display_reviews = util.string_as_bool( params.get( 'display_reviews', False ) )
- tool_file_contents = tarfile.open( tool.file_name, 'r' ).getnames()
- tra = self.get_user_item_rating( trans.sa_session, trans.user, tool, webapp_model=trans.model )
- visible_versions = trans.app.security_agent.get_visible_versions( trans.user, trans.user_is_admin(), cntrller, tool )
- if tool.is_rejected:
- # Include the comments regarding the reason for rejection
- reason_for_rejection = tool.latest_event.comment
- else:
- reason_for_rejection = ''
- return trans.fill_template( '/webapps/community/tool/view_tool.mako',
- avg_rating=avg_rating,
- categories=categories,
- can_approve_or_reject=can_approve_or_reject,
- can_delete=can_delete,
- can_download=can_download,
- can_edit=can_edit,
- can_purge=can_purge,
- can_rate=can_rate,
- can_upload_new_version=can_upload_new_version,
- can_view=can_view,
- cntrller=cntrller,
- display_reviews=display_reviews,
- num_ratings=num_ratings,
- reason_for_rejection=reason_for_rejection,
- tool=tool,
- tool_file_contents=tool_file_contents,
- tra=tra,
- visible_versions=visible_versions,
- message=message,
- status=status )
- @web.expose
- def delete_tool( self, trans, cntrller, **kwd ):
- params = util.Params( kwd )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- id = params.get( 'id', None )
- if not id:
- message='Select a tool to delete'
- status='error'
- else:
- tool = get_tool( trans, id )
- if not trans.app.security_agent.can_delete( trans.user, trans.user_is_admin(), cntrller, tool ):
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- cntrller=cntrller,
- message='You are not allowed to delete this tool',
- status='error' ) )
- # Create a new event
- event = trans.model.Event( state=trans.model.Tool.states.DELETED )
- # Flush so we can get an event id
- trans.sa_session.add( event )
- trans.sa_session.flush()
- # Associate the tool with the event
- tea = trans.model.ToolEventAssociation( tool=tool, event=event )
- # Delete the tool, keeping state for categories, events and versions
- tool.deleted = True
- trans.sa_session.add_all( ( tool, tea ) )
- trans.sa_session.flush()
- # TODO: What if the tool has versions, should they all be deleted?
- message = "Tool '%s' version %s has been marked deleted" % ( tool.name, tool.version )
- status = 'done'
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- cntrller=cntrller,
- message=message,
- status=status ) )
- @web.expose
- def download_tool( self, trans, cntrller, **kwd ):
- params = util.Params( kwd )
- id = params.get( 'id', None )
- if not id:
- return trans.response.send_redirect( web.url_for( controller='tool',
- action='browse_tools',
- cntrller=cntrller,
- message='Select a tool to download',
- status='error' ) )
- tool = get_tool( trans, id )
- if not trans.app.security_agent.can_download( trans.user, trans.user_is_admin(), cntrller, tool ):
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- cntrller=cntrller,
- message='You are not allowed to download this tool',
- status='error' ) )
- trans.response.set_content_type( tool.mimetype )
- trans.response.headers['Content-Length'] = int( os.stat( tool.file_name ).st_size )
- trans.response.headers['Content-Disposition'] = 'attachment; filename=%s' % tool.download_file_name
- return open( tool.file_name )
- @web.expose
- def upload_new_tool_version( self, trans, cntrller, **kwd ):
- params = util.Params( kwd )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- id = params.get( 'id', None )
- if not id:
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- cntrller=cntrller,
- message='Select a tool to upload a new version',
- status='error' ) )
- tool = get_tool( trans, id )
- if not trans.app.security_agent.can_upload_new_version( trans.user, tool ):
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- cntrller=cntrller,
- message='You are not allowed to upload a new version of this tool',
- status='error' ) )
- return trans.response.send_redirect( web.url_for( controller='tool_upload',
- action='upload',
- message=message,
- status=status,
- replace_id=id ) )
- @web.expose
- @web.require_login( "view tool history" )
- def view_tool_history( self, trans, cntrller, **kwd ):
- params = util.Params( kwd )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- id = params.get( 'id', None )
- if not id:
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- cntrller=cntrller,
- message='Select a tool to view its history',
- status='error' ) )
- tool = get_tool( trans, id )
- can_view = trans.app.security_agent.can_view( trans.user, trans.user_is_admin(), cntrller, tool )
- if not can_view:
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- cntrller=cntrller,
- message="You are not allowed to view this tool's history",
- status='error' ) )
- can_approve_or_reject = trans.app.security_agent.can_approve_or_reject( trans.user, trans.user_is_admin(), cntrller, tool )
- can_edit = trans.app.security_agent.can_edit( trans.user, trans.user_is_admin(), cntrller, tool )
- can_delete = trans.app.security_agent.can_delete( trans.user, trans.user_is_admin(), cntrller, tool )
- can_download = trans.app.security_agent.can_download( trans.user, trans.user_is_admin(), cntrller, tool )
- events = [ tea.event for tea in tool.events ]
- events = [ ( event.state, time_ago( event.update_time ), event.comment ) for event in events ]
- return trans.fill_template( '/webapps/community/common/view_tool_history.mako',
- cntrller=cntrller,
- events=events,
- tool=tool,
- can_approve_or_reject=can_approve_or_reject,
- can_edit=can_edit,
- can_delete=can_delete,
- can_download=can_download,
- can_view=can_view,
- message=message,
- status=status )
- @web.expose
- @web.require_login( "rate tools" )
- def rate_tool( self, trans, cntrller, **kwd ):
- """ Rate a tool and return updated rating data. """
- params = util.Params( kwd )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- id = params.get( 'id', None )
- if not id:
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- cntrller=cntrller,
- message='Select a tool to rate',
- status='error' ) )
- tool = get_tool( trans, id )
- can_rate = trans.app.security_agent.can_rate( trans.user, trans.user_is_admin(), cntrller, tool )
- if not can_rate:
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_tools',
- cntrller=cntrller,
- message="You are not allowed to rate this tool",
- status='error' ) )
- if params.get( 'rate_button', False ):
- rating = int( params.get( 'rating', '0' ) )
- comment = util.restore_text( params.get( 'comment', '' ) )
- rating = self.rate_item( trans, trans.user, tool, rating, comment )
- avg_rating, num_ratings = self.get_ave_item_rating_data( trans.sa_session, tool, webapp_model=trans.model )
- can_approve_or_reject = trans.app.security_agent.can_approve_or_reject( trans.user, trans.user_is_admin(), cntrller, tool )
- can_edit = trans.app.security_agent.can_edit( trans.user, trans.user_is_admin(), cntrller, tool )
- can_delete = trans.app.security_agent.can_delete( trans.user, trans.user_is_admin(), cntrller, tool )
- can_download = trans.app.security_agent.can_download( trans.user, trans.user_is_admin(), cntrller, tool )
- display_reviews = util.string_as_bool( params.get( 'display_reviews', False ) )
- tra = self.get_user_item_rating( trans.sa_session, trans.user, tool, webapp_model=trans.model )
- return trans.fill_template( '/webapps/community/common/rate_tool.mako',
- cntrller=cntrller,
- tool=tool,
- avg_rating=avg_rating,
- can_approve_or_reject=can_approve_or_reject,
- can_edit=can_edit,
- can_delete=can_delete,
- can_download=can_download,
- can_rate=can_rate,
- display_reviews=display_reviews,
- num_ratings=num_ratings,
- tra=tra,
- message=message,
- status=status )
-
## ---- Utility methods -------------------------------------------------------
-def get_versions( item ):
- """Get all versions of item"""
- versions = [ item ]
- this_item = item
- while item.newer_version:
- versions.insert( 0, item.newer_version )
- item = item.newer_version
- item = this_item
- while item.older_version:
- versions.append( item.older_version[ 0 ] )
- item = item.older_version[ 0 ]
- return versions
def get_categories( trans ):
"""Get all categories from the database"""
return trans.sa_session.query( trans.model.Category ) \
@@ -544,28 +44,6 @@
def get_category( trans, id ):
"""Get a category from the database"""
return trans.sa_session.query( trans.model.Category ).get( trans.security.decode_id( id ) )
-def get_tool( trans, id ):
- """Get a tool from the database"""
- return trans.sa_session.query( trans.model.Tool ).get( trans.security.decode_id( id ) )
-def get_latest_versions_of_tools( trans ):
- """Get only the latest version of each tool from the database"""
- return trans.sa_session.query( trans.model.Tool ) \
- .filter( trans.model.Tool.table.c.newer_version_id == None ) \
- .order_by( trans.model.Tool.table.c.name )
-def get_latest_versions_of_tools_by_state( trans, state ):
- """Get only the latest version of each tool whose state is the received state from the database"""
- tools = []
- for tool in trans.sa_session.query( trans.model.Tool ) \
- .order_by( trans.model.Tool.table.c.name ):
- if tool.state == state:
- tools.append( tool )
- return tools
-def get_event( trans, id ):
- """Get an event from the databse"""
- return trans.sa_session.query( trans.model.Event ).get( trans.security.decode_id( id ) )
-def get_user( trans, id ):
- """Get a user from the database"""
- return trans.sa_session.query( trans.model.User ).get( trans.security.decode_id( id ) )
def get_repository( trans, id ):
"""Get a repository from the database via id"""
return trans.sa_session.query( trans.model.Repository ).get( trans.security.decode_id( id ) )
@@ -577,3 +55,6 @@
tip_changeset = repository.changelog.tip()
tip_ctx = repository.changectx( tip_changeset )
return "%s:%s" % ( str( tip_ctx.rev() ), tip_ctx.parents()[0] )
+def get_user( trans, id ):
+ """Get a user from the database"""
+ return trans.sa_session.query( trans.model.User ).get( trans.security.decode_id( id ) )
--- a/lib/galaxy/webapps/community/controllers/repository.py Thu Jun 02 14:18:34 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/repository.py Thu Jun 02 15:18:35 2011 -0400
@@ -15,7 +15,7 @@
VALID_REPOSITORYNAME_RE = re.compile( "^[a-z0-9\_]+$" )
-class RepositoryCategoryListGrid( grids.Grid ):
+class CategoryListGrid( grids.Grid ):
# TODO rename this class to be categoryListGrid when we eliminate all the tools stuff.
class NameColumn( grids.TextColumn ):
def get_value( self, trans, grid, category ):
@@ -166,7 +166,7 @@
class RepositoryController( BaseController, ItemRatings ):
repository_list_grid = RepositoryListGrid()
- category_list_grid = RepositoryCategoryListGrid()
+ category_list_grid = CategoryListGrid()
@web.expose
def index( self, trans, **kwd ):
--- a/lib/galaxy/webapps/community/controllers/tool.py Thu Jun 02 14:18:34 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +0,0 @@
-import os, logging, urllib, tarfile
-
-from galaxy.web.base.controller import *
-from galaxy.webapps.community import model
-from galaxy.web.framework.helpers import time_ago, iff, grids
-from galaxy.model.orm import *
-# TODO: the following is bad because it imports the common controller.
-from common import *
-
-log = logging.getLogger( __name__ )
-
-class StateColumn( grids.StateColumn ):
- def get_value( self, trans, grid, tool ):
- state = tool.state
- if state == trans.model.Tool.states.APPROVED:
- state_color = 'ok'
- elif state == trans.model.Tool.states.REJECTED:
- state_color = 'error'
- elif state == trans.model.Tool.states.ARCHIVED:
- state_color = 'upload'
- else:
- state_color = state
- return '<div class="count-box state-color-%s">%s</div>' % ( state_color, state )
-
-class ToolStateColumn( grids.StateColumn ):
- def filter( self, trans, user, query, column_filter ):
- """Modify query to filter self.model_class by state."""
- if column_filter == "All":
- pass
- elif column_filter in [ v for k, v in self.model_class.states.items() ]:
- # Get all of the latest Events associated with the current version of each tool
- latest_event_id_for_current_versions_of_tools = [ tool.latest_event.id for tool in get_latest_versions_of_tools_by_state( trans, column_filter ) ]
- # Filter query by the latest state for the current version of each tool
- return query.filter( and_( model.Event.table.c.state == column_filter,
- model.Event.table.c.id.in_( latest_event_id_for_current_versions_of_tools ) ) )
- return query
-
-class ApprovedToolListGrid( ToolListGrid ):
- columns = [ col for col in ToolListGrid.columns ]
- columns.append(
- StateColumn( "Status",
- link=( lambda item: dict( operation="tools_by_state", id=item.id, webapp="community" ) ),
- visible=False,
- attach_popup=False )
- )
- columns.append(
- ToolStateColumn( "State",
- key="state",
- visible=False,
- filterable="advanced" )
- )
-
-class MyToolsListGrid( ApprovedToolListGrid ):
- columns = [ col for col in ToolListGrid.columns ]
- columns.append(
- StateColumn( "Status",
- link=( lambda item: dict( operation="tools_by_state", id=item.id, webapp="community" ) ),
- visible=True,
- attach_popup=False )
- )
- columns.append(
- ToolStateColumn( "State",
- key="state",
- visible=False,
- filterable="advanced" )
- )
-
-class ToolCategoryListGrid( CategoryListGrid ):
- """
- Replaces the tools column in the Category grid with a similar column,
- but displaying the number of APPROVED tools in the category.
- """
- class ToolsColumn( grids.TextColumn ):
- def get_value( self, trans, grid, category ):
- if category.tools:
- viewable_tools = 0
- for tca in category.tools:
- tool = tca.tool
- if tool.is_approved:
- viewable_tools += 1
- return viewable_tools
- return 0
-
- columns = []
- for col in CategoryListGrid.columns:
- if not isinstance( col, CategoryListGrid.ToolsColumn ):
- columns.append( col )
- columns.append(
- ToolsColumn( "Tools",
- model_class=model.Tool,
- attach_popup=False )
- )
-
-class ToolController( BaseController ):
-
- tool_list_grid = ApprovedToolListGrid()
- my_tools_list_grid = MyToolsListGrid()
- category_list_grid = ToolCategoryListGrid()
-
- @web.expose
- def index( self, trans, **kwd ):
- params = util.Params( kwd )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- return trans.fill_template( '/webapps/community/index.mako', message=message, status=status )
- @web.expose
- def browse_categories( self, trans, **kwd ):
- if 'operation' in kwd:
- operation = kwd['operation'].lower()
- if operation in [ "tools_by_category", "tools_by_state", "tools_by_user" ]:
- # Eliminate the current filters if any exist.
- for k, v in kwd.items():
- if k.startswith( 'f-' ):
- del kwd[ k ]
- return trans.response.send_redirect( web.url_for( controller='tool',
- action='browse_tools',
- cntrller='tool',
- **kwd ) )
- # Render the list view
- return self.category_list_grid( trans, **kwd )
- @web.expose
- def browse_tools( self, trans, **kwd ):
- # We add params to the keyword dict in this method in order to rename the param
- # with an "f-" prefix, simulating filtering by clicking a search link. We have
- # to take this approach because the "-" character is illegal in HTTP requests.
- if 'operation' not in kwd:
- # We may have been redirected here after performing an action. If we were
- # redirected from the tool controller, we have to add the default tools_by_category
- # operation to kwd so only tools we should see are displayed. This implies that
- # all redirectes from the tool controller added the cntrller value to kwd when
- # redirecting.
- cntrller = kwd.get( 'cntrller', None )
- if cntrller == 'tool':
- kwd[ 'operation' ] = 'approved_tools'
- if 'operation' in kwd:
- operation = kwd['operation'].lower()
- if operation == "view_tool":
- return trans.response.send_redirect( web.url_for( controller='common',
- action='view_tool',
- cntrller='tool',
- **kwd ) )
- elif operation == "edit_tool":
- return trans.response.send_redirect( web.url_for( controller='common',
- action='edit_tool',
- cntrller='tool',
- **kwd ) )
- elif operation == "download tool":
- return trans.response.send_redirect( web.url_for( controller='common',
- action='download_tool',
- cntrller='tool',
- **kwd ) )
- elif operation == "tools_by_user":
- # Eliminate the current filters if any exist.
- for k, v in kwd.items():
- if k.startswith( 'f-' ):
- del kwd[ k ]
- if 'user_id' in kwd:
- user = get_user( trans, kwd[ 'user_id' ] )
- kwd[ 'f-email' ] = user.email
- del kwd[ 'user_id' ]
- else:
- # The received id is the tool id, so we need to get the id of the user
- # that uploaded the tool.
- tool_id = kwd.get( 'id', None )
- tool = get_tool( trans, tool_id )
- kwd[ 'f-email' ] = tool.user.email
- elif operation == "my_tools":
- # Eliminate the current filters if any exist.
- for k, v in kwd.items():
- if k.startswith( 'f-' ):
- del kwd[ k ]
- kwd[ 'f-email' ] = trans.user.email
- return self.my_tools_list_grid( trans, **kwd )
- elif operation == "approved_tools":
- # Eliminate the current filters if any exist.
- for k, v in kwd.items():
- if k.startswith( 'f-' ):
- del kwd[ k ]
- # Make sure only the latest version of a tool whose state is APPROVED are displayed.
- kwd[ 'f-state' ] = trans.model.Tool.states.APPROVED
- return self.tool_list_grid( trans, **kwd )
- elif operation == "tools_by_category":
- # Eliminate the current filters if any exist.
- for k, v in kwd.items():
- if k.startswith( 'f-' ):
- del kwd[ k ]
- category_id = kwd.get( 'id', None )
- category = get_category( trans, category_id )
- kwd[ 'f-Category.name' ] = category.name
- # Make sure only the latest version of a tool whose state is APPROVED are displayed.
- kwd[ 'f-state' ] = trans.model.Tool.states.APPROVED
- # Render the list view
- return self.tool_list_grid( trans, **kwd )
- @web.expose
- def view_tool_file( self, trans, **kwd ):
- params = util.Params( kwd )
- id = params.get( 'id', None )
- if not id:
- return trans.response.send_redirect( web.url_for( controller='tool',
- action='browse_tools',
- cntrller='tool',
- message='Select a tool to download',
- status='error' ) )
- tool = get_tool( trans, id )
- tool_file_name = urllib.unquote_plus( kwd['file_name'] )
- tool_file = tarfile.open( tool.file_name ).extractfile( tool_file_name )
- trans.response.set_content_type( 'text/plain' )
- return tool_file
- @web.expose
- def help( self, trans, **kwd ):
- params = util.Params( kwd )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- return trans.fill_template( '/webapps/community/tool/help.mako', message=message, status=status, **kwd )
--- a/lib/galaxy/webapps/community/controllers/tool_upload.py Thu Jun 02 14:18:34 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,183 +0,0 @@
-import sys, os, shutil, logging, urllib2
-from galaxy.web.base.controller import *
-from galaxy.web.framework.helpers import time_ago, iff, grids
-from galaxy.model.orm import *
-from galaxy.web.form_builder import SelectField, build_select_field
-from galaxy.webapps.community import datatypes
-from common import get_categories, get_category, get_versions
-
-log = logging.getLogger( __name__ )
-
-# States for passing messages
-SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error"
-
-class UploadError( Exception ):
- pass
-
-class ToolUploadController( BaseController ):
-
- @web.expose
- @web.require_login( 'upload', use_panels=True, webapp='community' )
- def upload( self, trans, **kwd ):
- params = util.Params( kwd )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- category_ids = util.listify( params.get( 'category_id', '' ) )
- replace_id = params.get( 'replace_id', None )
- if replace_id:
- replace_version = trans.sa_session.query( trans.app.model.Tool ).get( trans.security.decode_id( replace_id ) )
- upload_type = replace_version.type
- else:
- replace_version = None
- upload_type = params.get( 'upload_type', 'tool' )
- uploaded_file = None
- categories = get_categories( trans )
- if not categories:
- message = 'No categories have been configured in this instance of the Galaxy Tool Shed. ' + \
- 'An administrator needs to create some via the Administrator control panel before anything can be uploaded',
- status = 'error'
- return trans.response.send_redirect( web.url_for( controller='tool',
- action='browse_tools',
- cntrller='tool',
- message=message,
- status=status ) )
- if params.get( 'upload_button', False ):
- url_paste = params.get( 'url', '' ).strip()
- file_data = params.get( 'file_data', '' )
- if file_data == '' and url_paste == '':
- message = 'No files were entered on the upload form.'
- status = 'error'
- elif file_data == '':
- try:
- uploaded_file = urllib2.urlopen( url_paste )
- except ( ValueError, urllib2.HTTPError ), e:
- message = 'An error occurred trying to retrieve the URL entered on the upload form: %s' % str( e )
- status = 'error'
- except urllib2.URLError, e:
- message = 'An error occurred trying to retrieve the URL entered on the upload form: %s' % e.reason
- status = 'error'
- elif file_data not in ( '', None ):
- uploaded_file = file_data.file
- if uploaded_file:
- datatype = trans.app.datatypes_registry.get_datatype_by_extension( upload_type )
- if datatype is None:
- message = 'An unknown file type was selected. This should not be possible, please report the error.'
- status = 'error'
- else:
- try:
- # Initialize the tool object
- meta = datatype.verify( uploaded_file )
- meta.user = trans.user
- meta.guid = trans.app.security.get_new_guid()
- meta.suite = upload_type == 'toolsuite'
- obj = datatype.create_model_object( meta )
- trans.sa_session.add( obj )
- if isinstance( obj, trans.app.model.Tool ):
- existing = trans.sa_session.query( trans.app.model.Tool ) \
- .filter_by( tool_id = meta.id ) \
- .first()
- if existing and not replace_id:
- raise UploadError( 'A %s with the same Id already exists. If you are trying to update this %s to a new version, use the upload form on the "Edit Tool" page. Otherwise, change the Id in the %s config.' % \
- ( obj.label, obj.label, obj.label ) )
- elif replace_id and not existing:
- raise UploadError( 'The new %s id (%s) does not match the old %s id (%s). Check the %s config files.' % \
- ( obj.label, str( meta.id ), obj.label, str( replace_version.tool_id ), obj.label ) )
- elif existing and replace_id:
- if replace_version.newer_version:
- # If the user has picked an old version, switch to the newest version
- replace_version = get_versions( replace_version )[0]
- if replace_version.tool_id != meta.id:
- raise UploadError( 'The new %s id (%s) does not match the old %s id (%s). Check the %s config files.' % \
- ( obj.label, str( meta.id ), obj.label, str( replace_version.tool_id ), obj.label ) )
- for old_version in get_versions( replace_version ):
- if old_version.version == meta.version:
- raise UploadError( 'The new version (%s) matches an old version. Check your version in the %s config file.' % \
- ( str( meta.version ), obj.label ) )
- if old_version.is_new:
- raise UploadError( 'There is an existing version of this %s which has not yet been submitted for approval, so either <a href="%s">submit it or delete it</a> before uploading a new version.' % \
- ( obj.label,
- url_for( controller='common',
- action='view_tool',
- cntrller='tool',
- id=trans.security.encode_id( old_version.id ) ) ) )
- if old_version.is_waiting:
- raise UploadError( 'There is an existing version of this %s which is waiting for administrative approval, so contact an administrator for help.' % \
- obj.label )
- # Defer setting the id since the newer version id doesn't exist until the new Tool object is flushed
- if category_ids:
- for category_id in category_ids:
- category = trans.app.model.Category.get( trans.security.decode_id( category_id ) )
- # Initialize the tool category
- tca = trans.app.model.ToolCategoryAssociation( obj, category )
- trans.sa_session.add( tca )
- # Initialize the tool event
- event = trans.app.model.Event( state=trans.app.model.Tool.states.NEW )
- # Flush to get an event id
- trans.sa_session.add( event )
- trans.sa_session.flush()
- tea = trans.app.model.ToolEventAssociation( obj, event )
- trans.sa_session.add( tea )
- if replace_version and replace_id:
- replace_version.newer_version_id = obj.id
- trans.sa_session.add( replace_version )
- # TODO: should the state be changed to archived? We'll leave it alone for now
- # because if the newer version is deleted, we'll need to add logic to reset the
- # the older version back to it's previous state ( possible approved ).
- comment = "Replaced by new version %s" % obj.version
- event = trans.app.model.Event( state=replace_version.state, comment=comment )
- # Flush to get an event id
- trans.sa_session.add( event )
- trans.sa_session.flush()
- tea = trans.app.model.ToolEventAssociation( replace_version, event )
- trans.sa_session.flush()
- try:
- os.link( uploaded_file.name, obj.file_name )
- except OSError:
- shutil.copy( uploaded_file.name, obj.file_name )
- # We're setting cntrller to 'tool' since that is the only controller from which we can upload
- # TODO: this will need tweaking when we can upload histories or workflows
- return trans.response.send_redirect( web.url_for( controller='common',
- action='edit_tool',
- cntrller='tool',
- id=trans.app.security.encode_id( obj.id ),
- message='Uploaded %s' % meta.message,
- status='done' ) )
- except ( datatypes.DatatypeVerificationError, UploadError ), e:
- message = str( e )
- status = 'error'
- uploaded_file.close()
- elif replace_id is not None:
- old_version = None
- for old_version in get_versions( replace_version ):
- if old_version.is_new:
- message = 'There is an existing version of this tool which has not been submitted for approval, so either submit or delete it before uploading a new version.'
- break
- if old_version.is_waiting:
- message = 'There is an existing version of this tool which is waiting for administrative approval, so contact an administrator for help.'
- break
- else:
- old_version = None
- if old_version is not None:
- return trans.response.send_redirect( web.url_for( controller='common',
- action='view_tool',
- cntrller='tool',
- id=trans.app.security.encode_id( old_version.id ),
- message=message,
- status='error' ) )
- selected_categories = [ trans.security.decode_id( id ) for id in category_ids ]
- datatype_extensions = trans.app.datatypes_registry.get_datatype_extensions()
- upload_type_select_list = build_select_field( trans,
- objs=datatype_extensions,
- label_attr='self',
- select_field_name='upload_type',
- initial_value=upload_type,
- selected_value=upload_type,
- refresh_on_change=True )
- return trans.fill_template( '/webapps/community/upload/upload.mako',
- message=message,
- status=status,
- selected_upload_type=upload_type,
- upload_type_select_list=upload_type_select_list,
- replace_id=replace_id,
- selected_categories=selected_categories,
- categories=get_categories( trans ) )
--- a/lib/galaxy/webapps/community/model/mapping.py Thu Jun 02 14:18:34 2011 -0400
+++ b/lib/galaxy/webapps/community/model/mapping.py Thu Jun 02 15:18:35 2011 -0400
@@ -122,22 +122,6 @@
Column( "repository_id", Integer, ForeignKey( "repository.id" ), index=True ),
Column( "category_id", Integer, ForeignKey( "category.id" ), index=True ) )
-Tool.table = Table( "tool", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "guid", TrimmedString( 255 ), index=True, unique=True ),
- Column( "tool_id", TrimmedString( 255 ), index=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "newer_version_id", Integer, ForeignKey( "tool.id" ), nullable=True ),
- Column( "name", TrimmedString( 255 ), index=True ),
- Column( "description" , TEXT ),
- Column( "user_description" , TEXT ),
- Column( "version", TrimmedString( 255 ) ),
- Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
- Column( "external_filename" , TEXT ),
- Column( "deleted", Boolean, index=True, default=False ),
- Column( "suite", Boolean, default=False, index=True ) )
-
Category.table = Table( "category", metadata,
Column( "id", Integer, primary_key=True ),
Column( "create_time", DateTime, default=now ),
@@ -146,32 +130,6 @@
Column( "description" , TEXT ),
Column( "deleted", Boolean, index=True, default=False ) )
-ToolCategoryAssociation.table = Table( "tool_category_association", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "tool_id", Integer, ForeignKey( "tool.id" ), index=True ),
- Column( "category_id", Integer, ForeignKey( "category.id" ), index=True ) )
-
-Event.table = Table( 'event', metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "state", TrimmedString( 255 ), index=True ),
- Column( "comment", TEXT ) )
-
-ToolEventAssociation.table = Table( "tool_event_association", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "tool_id", Integer, ForeignKey( "tool.id" ), index=True ),
- Column( "event_id", Integer, ForeignKey( "event.id" ), index=True ) )
-
-ToolRatingAssociation.table = Table( "tool_rating_association", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "tool_id", Integer, ForeignKey( "tool.id" ), index=True ),
- Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
- Column( "rating", Integer, index=True ),
- Column( "comment", TEXT ) )
-
Tag.table = Table( "tag", metadata,
Column( "id", Integer, primary_key=True ),
Column( "type", Integer ),
@@ -179,27 +137,10 @@
Column( "name", TrimmedString(255) ),
UniqueConstraint( "name" ) )
-ToolTagAssociation.table = Table( "tool_tag_association", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "tool_id", Integer, ForeignKey( "tool.id" ), index=True ),
- Column( "tag_id", Integer, ForeignKey( "tag.id" ), index=True ),
- Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
- Column( "user_tname", TrimmedString(255), index=True),
- Column( "value", TrimmedString(255), index=True),
- Column( "user_value", TrimmedString(255), index=True) )
-
-ToolAnnotationAssociation.table = Table( "tool_annotation_association", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "tool_id", Integer, ForeignKey( "tool.id" ), index=True ),
- Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
- Column( "annotation", TEXT, index=True) )
-
# With the tables defined we can define the mappers and setup the
# relationships between the model objects.
assign_mapper( context, User, User.table,
- properties=dict( tools=relation( Tool, primaryjoin=( Tool.table.c.user_id == User.table.c.id ), order_by=( Tool.table.c.name ) ),
- active_tools=relation( Tool, primaryjoin=( ( Tool.table.c.user_id == User.table.c.id ) & ( not_( Tool.table.c.deleted ) ) ), order_by=( Tool.table.c.name ) ),
- active_repositories=relation( Repository, primaryjoin=( ( Repository.table.c.user_id == User.table.c.id ) & ( not_( Repository.table.c.deleted ) ) ), order_by=( Repository.table.c.name ) ),
+ properties=dict( active_repositories=relation( Repository, primaryjoin=( ( Repository.table.c.user_id == User.table.c.id ) & ( not_( Repository.table.c.deleted ) ) ), order_by=( Repository.table.c.name ) ),
galaxy_sessions=relation( GalaxySession, order_by=desc( GalaxySession.table.c.update_time ) ) ) )
assign_mapper( context, Group, Group.table,
@@ -233,49 +174,8 @@
assign_mapper( context, Tag, Tag.table,
properties=dict( children=relation(Tag, backref=backref( 'parent', remote_side=[Tag.table.c.id] ) ) ) )
-assign_mapper( context, ToolTagAssociation, ToolTagAssociation.table,
- properties=dict( tag=relation(Tag, backref="tagged_tools"), user=relation( User ) ) )
-
-assign_mapper( context, ToolAnnotationAssociation, ToolAnnotationAssociation.table,
- properties=dict( tool=relation( Tool ), user=relation( User ) ) )
-
-assign_mapper( context, Tool, Tool.table,
- properties = dict(
- categories=relation( ToolCategoryAssociation ),
- events=relation( ToolEventAssociation, secondary=Event.table,
- primaryjoin=( Tool.table.c.id==ToolEventAssociation.table.c.tool_id ),
- secondaryjoin=( ToolEventAssociation.table.c.event_id==Event.table.c.id ),
- order_by=desc( Event.table.c.update_time ),
- viewonly=True,
- uselist=True ),
- ratings=relation( ToolRatingAssociation, order_by=desc( ToolRatingAssociation.table.c.update_time ), backref="tools" ),
- user=relation( User.mapper ),
- older_version=relation(
- Tool,
- primaryjoin=( Tool.table.c.newer_version_id == Tool.table.c.id ),
- backref=backref( "newer_version", primaryjoin=( Tool.table.c.newer_version_id == Tool.table.c.id ), remote_side=[Tool.table.c.id] ) )
- ) )
-
-
-assign_mapper( context, ToolCategoryAssociation, ToolCategoryAssociation.table,
- properties=dict(
- category=relation( Category ),
- tool=relation( Tool ) ) )
-
-assign_mapper( context, ToolRatingAssociation, ToolRatingAssociation.table,
- properties=dict( tool=relation( Tool ), user=relation( User ) ) )
-
-assign_mapper( context, Event, Event.table,
- properties=None )
-
-assign_mapper( context, ToolEventAssociation, ToolEventAssociation.table,
- properties=dict(
- tool=relation( Tool ),
- event=relation( Event ) ) )
-
assign_mapper( context, Category, Category.table,
- properties=dict( tools=relation( ToolCategoryAssociation ),
- repositories=relation( RepositoryCategoryAssociation ) ) )
+ properties=dict( repositories=relation( RepositoryCategoryAssociation ) ) )
assign_mapper( context, Repository, Repository.table,
properties = dict(
@@ -309,11 +209,8 @@
# Let this go, it could possibly work with db's we don't support
log.error( "database_connection contains an unknown SQLAlchemy database dialect: %s" % dialect )
-def init( enable_next_gen_tool_shed, file_path, url, engine_options={}, create_tables=False ):
+def init( file_path, url, engine_options={}, create_tables=False ):
"""Connect mappings to the database"""
- if not enable_next_gen_tool_shed:
- # Connect tool archive location to the file path
- Tool.file_path = file_path
# Load the appropriate db module
load_egg_for_url( url )
# Create the database engine
--- a/lib/galaxy/webapps/community/security/__init__.py Thu Jun 02 14:18:34 2011 -0400
+++ b/lib/galaxy/webapps/community/security/__init__.py Thu Jun 02 15:18:35 2011 -0400
@@ -6,7 +6,6 @@
from galaxy.util.bunch import Bunch
from galaxy.util import listify
from galaxy.model.orm import *
-from galaxy.webapps.community.controllers.common import get_versions
log = logging.getLogger(__name__)
@@ -77,8 +76,6 @@
elif 'role' in kwd:
if 'group' in kwd:
return self.associate_group_role( kwd['group'], kwd['role'] )
- elif 'tool' in kwd:
- return self.associate_tool_category( kwd['tool'], kwd['category'] )
elif 'repository' in kwd:
return self.associate_repository_category( kwd[ 'repository' ], kwd[ 'category' ] )
raise 'No valid method of associating provided components: %s' % kwd
@@ -97,11 +94,6 @@
self.sa_session.add( assoc )
self.sa_session.flush()
return assoc
- def associate_tool_category( self, tool, category ):
- assoc = self.model.ToolCategoryAssociation( tool, category )
- self.sa_session.add( assoc )
- self.sa_session.flush()
- return assoc
def associate_repository_category( self, repository, category ):
assoc = self.model.RepositoryCategoryAssociation( repository, category )
self.sa_session.add( assoc )
@@ -162,77 +154,6 @@
self.associate_components( user=user, role=role )
for group in groups:
self.associate_components( user=user, group=group )
- def set_entity_category_associations( self, tools=[], categories=[], delete_existing_assocs=True ):
- for tool in tools:
- if delete_existing_assocs:
- for a in tool.categories:
- self.sa_session.delete( a )
- self.sa_session.flush()
- self.sa_session.refresh( tool )
- for category in categories:
- self.associate_components( tool=tool, category=category )
- def can_rate( self, user, user_is_admin, cntrller, item ):
- # The current user can rate and review the item if they are an admin or if
- # they did not upload the item and the item is approved or archived.
- if user and user_is_admin and cntrller == 'admin':
- return True
- if cntrller in [ 'tool' ] and ( item.is_approved or item.is_archived ) and user != item.user:
- return True
- return False
- def can_approve_or_reject( self, user, user_is_admin, cntrller, item ):
- # The current user can approve or reject the item if the user
- # is an admin, and the item's state is WAITING.
- return user and user_is_admin and cntrller=='admin' and item.is_waiting
- def can_delete( self, user, user_is_admin, cntrller, item ):
- # The current user can delete the item if they are an admin or if they uploaded the
- # item and in either case the item's state is not DELETED.
- if user and user_is_admin and cntrller == 'admin':
- can_delete = not item.is_deleted
- elif cntrller in [ 'tool' ]:
- can_delete = user==item.user and not item.is_deleted
- else:
- can_delete = False
- return can_delete
- def can_download( self, user, user_is_admin, cntrller, item ):
- # The current user can download the item if they are an admin or if the
- # item's state is not one of: NEW, WAITING.
- if user and user_is_admin and cntrller == 'admin':
- return True
- elif cntrller in [ 'tool' ]:
- can_download = not( item.is_new or item.is_waiting )
- else:
- can_download = False
- return can_download
- def can_edit( self, user, user_is_admin, cntrller, item ):
- # The current user can edit the item if they are an admin or if they uploaded the item
- # and the item's state is one of: NEW, REJECTED.
- if user and user_is_admin and cntrller == 'admin':
- return True
- if cntrller in [ 'tool' ]:
- return user and user==item.user and ( item.is_new or item.is_rejected )
- return False
- def can_purge( self, user, user_is_admin, cntrller ):
- # The current user can purge the item if they are an admin.
- return user and user_is_admin and cntrller == 'admin'
- def can_upload_new_version( self, user, item ):
- # The current user can upload a new version as long as the item's state is not NEW or WAITING.
- if not user:
- return False
- versions = get_versions( item )
- state_ok = True
- for version in versions:
- if version.is_new or version.is_waiting:
- state_ok = False
- break
- return state_ok
- def can_view( self, user, user_is_admin, cntrller, item ):
- # The current user can view the item if they are an admin or if they uploaded the item
- # or if the item's state is APPROVED.
- if user and user_is_admin and cntrller == 'admin':
- return True
- if cntrller in [ 'tool' ] and item.is_approved or item.is_archived or item.is_deleted:
- return True
- return user and user==item.user
def can_push( self, user, repository ):
# TODO: handle this via the mercurial api.
if not user:
@@ -246,29 +167,6 @@
allowed = config.get( "web", option )
return user.username in allowed
return False
- def get_all_action_permissions( self, user, user_is_admin, cntrller, item ):
- """Get all permitted actions on item for the current user"""
- can_edit = self.can_edit( cntrller, user, user_is_admin, item )
- can_view = self.can_view( cntrller, user, user_is_admin, item )
- can_upload_new_version = self.can_upload_new_version( user, item )
- visible_versions = self.get_visible_versions( user, user_is_admin, cntrller, item )
- can_approve_or_reject = self.can_approve_or_reject( user, user_is_admin, cntrller, item )
- can_delete = self.can_delete( user, user_is_admin, cntrller, item )
- return can_edit, can_view, can_upload_new_version, can_delete, visible_versions, can_approve_or_reject
- def get_visible_versions( self, user, user_is_admin, cntrller, item ):
- # All previous versions of item can be displayed if the current user is an admin
- # or they uploaded item. Otherwise, only versions whose state is APPROVED or
- # ARCHIVED will be displayed.
- if user and user_is_admin and cntrller == 'admin':
- visible_versions = get_versions( item )
- elif cntrller in [ 'tool' ]:
- visible_versions = []
- for version in get_versions( item ):
- if version.is_approved or version.is_archived or version.user == user:
- visible_versions.append( version )
- else:
- visible_versions = []
- return visible_versions
def get_permitted_actions( filter=None ):
'''Utility method to return a subset of RBACAgent's permitted actions'''
--- a/scripts/tool_shed/migrate_tools_to_repositories.py Thu Jun 02 14:18:34 2011 -0400
+++ b/scripts/tool_shed/migrate_tools_to_repositories.py Thu Jun 02 15:18:35 2011 -0400
@@ -8,6 +8,8 @@
====== CRITICAL =======
+0. This script must be run on a repo updated to changeset: 5621:4618be57481b
+
1. Before running this script, make sure the following config setting is set in community_wsgi.ini
# Enable next-gen tool shed features
@@ -16,10 +18,6 @@
2. This script requires the Galaxy instance to use Postgres for database storage.
To run this script, use "sh migrate_tools_to_repositories.sh" from this directory
-
-TODO: This script currently creates hg repos under the name of the user running the script. When
-we get the hgweb stuff working, see if we can correct this, creating repos under the user name of the
-user that uploaded the tool archive.
'''
import sys, os, subprocess, ConfigParser, shutil, tarfile, tempfile
--- a/templates/webapps/community/admin/center.mako Thu Jun 02 14:18:34 2011 -0400
+++ b/templates/webapps/community/admin/center.mako Thu Jun 02 15:18:35 2011 -0400
@@ -6,26 +6,6 @@
<p>The menu on the left provides the following features</p><ul>
- %if not trans.app.config.enable_next_gen_tool_shed:
- <li>
- <strong>Tools</strong>
- <p/>
- <ul>
- <li>
- <strong>Tools awaiting approval</strong>
- </li>
- <p/>
- <li>
- <strong>Browse by category</strong>
- </li>
- <p/>
- <li>
- <strong>Browse all tools</strong>
- </li>
- <p/>
- </ul>
- </li>
- %endif
<li><strong>Categories</strong><p/>
--- a/templates/webapps/community/admin/index.mako Thu Jun 02 14:18:34 2011 -0400
+++ b/templates/webapps/community/admin/index.mako Thu Jun 02 15:18:35 2011 -0400
@@ -43,22 +43,8 @@
<div class="page-container" style="padding: 10px;"><div class="toolMenu"><div class="toolSectionList">
- %if trans.app.config.enable_next_gen_tool_shed:
- <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='browse_categories', webapp='community' )}">Browse by category</a></div>
- <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='browse_repositories', webapp='community' )}">Browse all repositories</a></div>
- %else:
- <div class="toolSectionTitle">
- <span>Tools</span>
- </div>
- <div class="toolSectionBody">
- <div class="toolSectionBg">
- <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='browse_tools', operation='tools_by_state', state=trans.model.Tool.states.WAITING, webapp='community' )}">Tools awaiting approval</a></div>
- <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='browse_categories', webapp='community' )}">Browse by category</a></div>
- <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='browse_tools', webapp='community' )}">Browse all tools</a></div>
- </div>
- </div>
- <div class="toolSectionPad"></div>
- %endif
+ <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='browse_categories', webapp='community' )}">Browse by category</a></div>
+ <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='browse_repositories', webapp='community' )}">Browse all repositories</a></div><div class="toolSectionTitle">
Categories
</div>
--- a/templates/webapps/community/admin/reject_tool.mako Thu Jun 02 14:18:34 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-<%namespace file="/message.mako" import="render_msg" />
-
-<%!
- def inherit(context):
- if context.get('use_panels'):
- return '/webapps/community/base_panels.mako'
- else:
- return '/base.mako'
-%>
-<%inherit file="${inherit(context)}"/>
-
-<%def name="title()">Reject Tool</%def>
-
-<h2>Reject Tool</h2>
-
-<ul class="manage-table-actions">
- <li><a class="action-button" id="tool-${tool.id}-popup" class="menubutton">Tool Actions</a></li>
- <div popupmenu="tool-${tool.id}-popup">
- <a class="action-button" href="${h.url_for( controller='common', action='view_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">View tool</a>
- <a class="action-button" href="${h.url_for( controller='common', action='view_tool_history', id=trans.security.encode_id( tool.id ), cntrller=cntrller )}">Tool history</a>
- <a class="action-button" href="${h.url_for( controller='common', action='download_tool', id=trans.security.encode_id( tool.id ), cntrller=cntrller )}">Download tool</a>
- </div>
-</ul>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<div class="toolForm">
- <div class="toolFormTitle">${tool.name}</div>
- <form name="reject_tool" action="${h.url_for( controller='admin', action='reject_tool', id=trans.security.encode_id( tool.id ) )}" method="post" >
- <div class="form-row">
- <label>Tool id:</label>
- ${tool.tool_id}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Version:</label>
- ${tool.version}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Description:</label>
- ${tool.description}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>User description:</label>
- ${tool.user_description}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Uploaded by:</label>
- ${tool.user.username}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Reason for rejection</label>
- <textarea name="comments" rows="5" cols="40"></textarea>
- <div class="toolParamHelp" style="clear: both;">
- Required
- </div>
- </div>
- <div class="form-row">
- <input type="submit" name="reject_button" value="Reject"/>
- <input type="submit" name="cancel_reject_button" value="Cancel"/>
- </div>
- </form>
- </div>
-</div>
--- a/templates/webapps/community/base_panels.mako Thu Jun 02 14:18:34 2011 -0400
+++ b/templates/webapps/community/base_panels.mako Thu Jun 02 15:18:35 2011 -0400
@@ -26,11 +26,7 @@
<td class="${cls}" style="${style}"><a target="${target}" href="${href}">${display}</a></td></%def>
- %if trans.app.config.enable_next_gen_tool_shed:
- ${tab( "repositories", "Repositories", h.url_for( controller='/repository', action='index', webapp='community' ) )}
- %else:
- ${tab( "tools", "Tools", h.url_for( controller='/tool', action='index', webapp='community' ) )}
- %endif
+ ${tab( "repositories", "Repositories", h.url_for( controller='/repository', action='index', webapp='community' ) )}
${tab( "admin", "Admin", h.url_for( controller='/admin', action='index', webapp='community' ), extra_class="admin-only", visible=( trans.user and app.config.is_admin_user( trans.user ) ) )}
<td class="tab">
--- a/templates/webapps/community/common/rate_tool.mako Thu Jun 02 14:18:34 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,212 +0,0 @@
-<%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/webapps/community/common/common.mako" import="*" />
-
-<%
- from galaxy.web.framework.helpers import time_ago
- from urllib import quote_plus
-
- if cntrller in [ 'tool' ] and can_edit:
- menu_label = 'Edit information or submit for approval'
- else:
- menu_label = 'Edit information'
-%>
-
-<%!
- def inherit(context):
- if context.get('use_panels'):
- return '/webapps/community/base_panels.mako'
- else:
- return '/base.mako'
-%>
-<%inherit file="${inherit(context)}"/>
-
-<%def name="stylesheets()">
- ${parent.stylesheets()}
- ${h.css( "jquery.rating" )}
- <style type="text/css">
- ul.fileBrowser,
- ul.toolFile {
- margin-left: 0;
- padding-left: 0;
- list-style: none;
- }
- ul.fileBrowser {
- margin-left: 20px;
- }
- .fileBrowser li,
- .toolFile li {
- padding-left: 20px;
- background-repeat: no-repeat;
- background-position: 0;
- min-height: 20px;
- }
- .toolFile li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white_compressed.png' )} );
- }
- .fileBrowser li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white.png' )} );
- }
- </style>
-</%def>
-
-<%def name="javascripts()">
- ${parent.javascripts()}
- ${h.js( "jquery.rating" )}
-</%def>
-
-<%def name="title()">Rate Tool</%def>
-
-<h2>Rate Tool</h2>
-
-${tool.get_state_message()}
-<p/>
-
-<ul class="manage-table-actions">
- %if can_approve_or_reject:
- <li><a class="action-button" href="${h.url_for( controller='admin', action='set_tool_state', state=trans.model.Tool.states.APPROVED, id=trans.security.encode_id( tool.id ), cntrller=cntrller )}">Approve</a></li>
- <li><a class="action-button" href="${h.url_for( controller='admin', action='set_tool_state', state=trans.model.Tool.states.REJECTED, id=trans.security.encode_id( tool.id ), cntrller=cntrller )}">Reject</a></li>
- %endif
- <li><a class="action-button" id="tool-${tool.id}-popup" class="menubutton">Tool Actions</a></li>
- <div popupmenu="tool-${tool.id}-popup">
- %if can_edit:
- <a class="action-button" href="${h.url_for( controller='common', action='edit_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">${menu_label}</a>
- %endif
- <a class="action-button" href="${h.url_for( controller='common', action='view_tool_history', id=trans.security.encode_id( tool.id ), cntrller=cntrller )}">Tool history</a>
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='common', action='download_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">Download tool</a>
- %endif
- %if can_delete:
- <a class="action-button" href="${h.url_for( controller='common', action='delete_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}" confirm="Are you sure you want to delete this tool?">Delete tool</a>
- %endif
- %if can_upload_new_version:
- <a class="action-button" href="${h.url_for( controller='common', action='upload_new_tool_version', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">Upload a new version</a>
- %endif
- %if can_purge:
- <li><a class="action-button" href="${h.url_for( controller='admin', action='purge_tool', id=trans.security.encode_id( tool.id ), cntrller=cntrller )}" confirm="Purging removes records from the database, are you sure you want to purge this tool?">Purge tool</a></li>
- %endif
- </div>
-</ul>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-%if can_rate:
- <div class="toolForm">
- <div class="toolFormTitle">${tool.name}</div>
- <div class="toolFormBody">
- <div class="form-row">
- <label>Tool Id:</label>
- ${tool.tool_id}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Version:</label>
- ${tool.version}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Description:</label>
- ${tool.description}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>User Description:</label>
- %if tool.user_description:
- <pre>${tool.user_description}</pre>
- %endif
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Uploaded By:</label>
- ${tool.user.username}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Date Uploaded:</label>
- ${time_ago( tool.create_time )}
- <div style="clear: both"></div>
- </div>
- </div>
- </div>
- <p/>
- <div class="toolForm">
- <div class="toolFormTitle">Rate and Review</div>
- <div class="toolFormBody">
- <form id="rate_tool" name="rate_tool" action="${h.url_for( controller='common', action='rate_tool', id=trans.security.encode_id( tool.id ), cntrller=cntrller )}" method="post">
- <div class="form-row">
- <label>Times Rated:</label>
- ${num_ratings}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Average Rating:</label>
- ${render_star_rating( 'avg_rating', avg_rating, disabled=True )}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Your Rating:</label>
- <%
- if tra and tra.rating:
- rating = tra.rating
- else:
- rating = 0
- %>
- ${render_star_rating( 'rating', rating )}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Review:</label>
- %if tra and tra.comment:
- <div class="form-row-input"><textarea name="comment" rows="5" cols="35">${tra.comment}</textarea></div>
- %else:
- <div class="form-row-input"><textarea name="comment" rows="5" cols="35"></textarea></div>
- %endif
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <input type="submit" name="rate_button" id="rate_button" value="Submit" />
- </div>
- </form>
- </div>
- </div>
- <p/>
- %if tool.ratings and ( len( tool.ratings ) > 1 or tool.ratings[0] != tra ):
- <div class="toolForm">
- <div class="toolFormBody">
- %if display_reviews:
- <div class="form-row">
- <a href="${h.url_for( controller='common', action='rate_tool', id=trans.security.encode_id( tool.id ), cntrller=cntrller, display_reviews=False )}"><label>Hide Reviews</label></a>
- </div>
- <table class="grid">
- <thead>
- <tr>
- <th>Rating</th>
- <th>Comments</th>
- <th>Reviewed</th>
- <th>User</th>
- </tr>
- </thead>
- <% count = 0 %>
- %for review in tool.ratings:
- <%
- count += 1
- name = 'rating%d' % count
- %>
- <tr>
- <td>${render_star_rating( name, review.rating, disabled=True )}</td>
- <td>${review.comment}</td>
- <td>${time_ago( review.update_time )}</td>
- <td>${review.user.username}</td>
- </tr>
- %endfor
- </table>
- %else:
- <div class="form-row">
- <a href="${h.url_for( controller='common', action='rate_tool', id=trans.security.encode_id( tool.id ), cntrller=cntrller, display_reviews=True )}"><label>Display Reviews</label></a>
- </div>
- %endif
- </div>
- </div>
- %endif
-%endif
--- a/templates/webapps/community/common/view_tool_history.mako Thu Jun 02 14:18:34 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-<%namespace file="/message.mako" import="render_msg" />
-
-<%
- if cntrller in [ 'tool' ] and can_edit:
- menu_label = 'Edit information or submit for approval'
- else:
- menu_label = 'Edit information'
-%>
-
-<%!
- def inherit(context):
- if context.get('use_panels'):
- return '/webapps/community/base_panels.mako'
- else:
- return '/base.mako'
-%>
-<%inherit file="${inherit(context)}"/>
-
-<h2>Tool history</h2>
-<ul class="manage-table-actions">
- %if can_approve_or_reject:
- <li><a class="action-button" href="${h.url_for( controller='admin', action='set_tool_state', state=trans.model.Tool.states.APPROVED, id=trans.security.encode_id( tool.id ), cntrller=cntrller )}">Approve</a></li>
- <li><a class="action-button" href="${h.url_for( controller='admin', action='set_tool_state', state=trans.model.Tool.states.REJECTED, id=trans.security.encode_id( tool.id ), cntrller=cntrller )}">Reject</a></li>
- %endif
- <li><a class="action-button" id="tool-${tool.id}-popup" class="menubutton">Tool Actions</a></li>
- <div popupmenu="tool-${tool.id}-popup">
- %if can_edit:
- <a class="action-button" href="${h.url_for( controller='common', action='edit_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">${menu_label}</a>
- %endif
- %if can_view:
- <a class="action-button" href="${h.url_for( controller='common', action='view_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">View tool</a>
- %endif
- %if can_delete:
- <a class="action-button" href="${h.url_for( controller='common', action='delete_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}" confirm="Are you sure you want to delete this tool?">Delete tool</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='common', action='download_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">Download tool</a>
- %endif
- </div>
-</ul>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<div class="toolForm">
- <div class="toolFormTitle">${tool.name}</div>
- <div class="form-row">
- <label>Tool id:</label>
- ${tool.tool_id}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Version:</label>
- ${tool.version}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Description:</label>
- ${tool.description}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>User description:</label>
- ${tool.user_description}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Uploaded by:</label>
- ${tool.user.username}
- <div style="clear: both"></div>
- </div>
-</div>
-<p/>
-<table class="grid">
- <thead>
- <tr>
- <th>State</th>
- <th>Last Update</th>
- <th>Comments</th>
- </tr>
- </thead>
- <tbody>
- %for state, updated, comments in events:
- <tr class="libraryRow libraryOrFolderRow" id="libraryRow">
- <td><b><a>${state}</a></b></td>
- <td><a>${updated}</a></td>
- <td><a>${comments}</a></td>
- </tr>
- %endfor
- </tbody>
-</table>
--- a/templates/webapps/community/index.mako Thu Jun 02 14:18:34 2011 -0400
+++ b/templates/webapps/community/index.mako Thu Jun 02 15:18:35 2011 -0400
@@ -45,45 +45,23 @@
<div class="toolMenu"><div class="toolSectionList"><div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- %if trans.app.config.enable_next_gen_tool_shed:
- Repositories
- %else:
- Tools
- %endif
- </div>
+ <div class="toolSectionTitle">Repositories</div><div class="toolSectionBody"><div class="toolSectionBg">
- %if trans.app.config.enable_next_gen_tool_shed:
- <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_categories', webapp='community' )}">Browse by category</a></div>
- <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', webapp='community' )}">Browse all repositories</a></div>
- %if trans.user:
- <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='my_repositories', webapp='community' )}">Browse your repositories</a></div>
- %endif
- %else:
- <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='tool', action='browse_categories', webapp='community' )}">Browse by category</a></div>
- <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='tool', action='browse_tools', operation='approved_tools', webapp='community' )}">Browse all tools</a></div>
- %if trans.user:
- <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='tool', action='browse_tools', operation='my_tools', webapp='community' )}">Browse your tools</a></div>
- %endif
+ <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_categories', webapp='community' )}">Browse by category</a></div>
+ <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', webapp='community' )}">Browse all repositories</a></div>
+ %if trans.user:
+ <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='my_repositories', webapp='community' )}">Browse my repositories</a></div>
%endif
</div></div><div class="toolSectionBody"><div class="toolSectionBg"><div class="toolTitle">
- %if trans.app.config.enable_next_gen_tool_shed:
- %if trans.user:
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='create_repository', webapp='community' )}">Create new repository</a>
- %else:
- <a target="galaxy_main" href="${h.url_for( controller='/user', action='login', webapp='community' )}">Login to create a repository</a>
- %endif
+ %if trans.user:
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='create_repository', webapp='community' )}">Create new repository</a>
%else:
- %if trans.user:
- <a target="galaxy_main" href="${h.url_for( controller='tool_upload', action='upload', type='tool', webapp='community' )}">Upload a tool</a>
- %else:
- <a target="galaxy_main" href="${h.url_for( controller='/user', action='login', webapp='community' )}">Login to upload</a>
- %endif
+ <a target="galaxy_main" href="${h.url_for( controller='/user', action='login', webapp='community' )}">Login to create a repository</a>
%endif
</div></div>
@@ -97,10 +75,8 @@
<%
if trans.app.config.require_login and not trans.user:
center_url = h.url_for( controller='user', action='login', message=message, status=status, webapp='community' )
- elif trans.app.config.enable_next_gen_tool_shed:
+ else:
center_url = h.url_for( controller='repository', action='browse_categories', message=message, status=status, webapp='community' )
- else:
- center_url = h.url_for( controller='tool', action='browse_categories', message=message, status=status, webapp='community' )
%><iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${center_url}"></iframe></%def>
--- a/templates/webapps/community/tool/edit_tool.mako Thu Jun 02 14:18:34 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-<%
- from galaxy.web.framework.helpers import time_ago
-%>
-
-<%!
- def inherit(context):
- if context.get('use_panels'):
- return '/webapps/community/base_panels.mako'
- else:
- return '/base.mako'
-%>
-<%inherit file="${inherit(context)}"/>
-
-<%def name="javascripts()">
- ${parent.javascripts()}
- <script type="text/javascript">
- $(function(){
- $("input:text:first").focus();
- })
- function confirmSubmit() {
- if ( confirm( "Make sure you have filled in the User Description field. After you have submitted your tool to be published, you will no longer be able to modify it. Click OK to submit it." ) ) {
- return true;
- } else {
- return false;
- }
- }
- </script>
-</%def>
-
-<%def name="render_select( name, options )">
- <select name="${name}" id="${name}" style="min-width: 250px; height: 150px;" multiple>
- %for option in options:
- <option value="${option[0]}">${option[1]}</option>
- %endfor
- </select>
-</%def>
-
-<script type="text/javascript">
-$().ready(function() {
- $('#categories_add_button').click(function() {
- return !$('#out_categories option:selected').remove().appendTo('#in_categories');
- });
- $('#categories_remove_button').click(function() {
- return !$('#in_categories option:selected').remove().appendTo('#out_categories');
- });
- $('form#edit_tool').submit(function() {
- $('#in_categories option').each(function(i) {
- $(this).attr("selected", "selected");
- });
- });
-});
-</script>
-
-<%def name="title()">Edit Tool</%def>
-
-<h2>Edit Tool</h2>
-
-${tool.get_state_message()}
-<p/>
-
-<ul class="manage-table-actions">
- %if can_approve_or_reject:
- <li><a class="action-button" href="${h.url_for( controller='admin', action='set_tool_state', state=trans.model.Tool.states.APPROVED, id=trans.security.encode_id( tool.id ), cntrller=cntrller )}">Approve</a></li>
- <li><a class="action-button" href="${h.url_for( controller='admin', action='set_tool_state', state=trans.model.Tool.states.REJECTED, id=trans.security.encode_id( tool.id ), cntrller=cntrller )}">Reject</a></li>
- %endif
- <li><a class="action-button" id="tool-${tool.id}-popup" class="menubutton">Tool Actions</a></li>
- <div popupmenu="tool-${tool.id}-popup">
- %if can_view:
- <a class="action-button" href="${h.url_for( controller='common', action='view_tool_history', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">Tool history</a>
- <a class="action-button" href="${h.url_for( controller='common', action='view_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">View tool</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='common', action='download_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">Download tool</a>
- %endif
- %if can_delete:
- <a class="action-button" href="${h.url_for( controller='common', action='delete_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}" confirm="Are you sure you want to delete this tool?">Delete tool</a>
- %endif
- %if can_upload_new_version:
- <a class="action-button" href="${h.url_for( controller='common', action='upload_new_tool_version', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">Upload a new version</a>
- %endif
- %if can_purge:
- <li><a class="action-button" href="${h.url_for( controller='admin', action='purge_tool', id=trans.security.encode_id( tool.id ), cntrller=cntrller )}" confirm="Purging removes records from the database, are you sure you want to purge this tool?">Purge tool</a></li>
- %endif
- </div>
-</ul>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-%if can_edit:
- <form id="edit_tool" name="edit_tool" action="${h.url_for( controller='common', action='edit_tool' )}" method="post">
- %if tool.is_rejected:
- <div class="toolForm">
- <div class="toolFormTitle">Reason for rejection</div>
- <div class="toolFormBody">
- <div class="form-row">
- ${reason_for_rejection}
- <div style="clear: both"></div>
- </div>
- </div>
- </div>
- <p/>
- %endif
- <div class="toolForm">
- <div class="toolFormTitle">${tool.name}</div>
- <div class="toolFormBody">
- <input type="hidden" name="id" value="${trans.app.security.encode_id( tool.id )}"/>
- <input type="hidden" name="cntrller" value="${cntrller}"/>
- <div class="form-row">
- <label>Tool Id:</label>
- ${tool.tool_id}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Version:</label>
- ${tool.version}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Description:</label>
- ${tool.description}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>User Description:</label>
- %if tool.user_description:
- <div class="form-row-input"><pre><textarea name="user_description" rows="5" cols="35">${tool.user_description}</textarea></pre></div>
- %else:
- <div class="form-row-input"><textarea name="user_description" rows="5" cols="35"></textarea></div>
- %endif
- <div class="toolParamHelp" style="clear: both;">Required when submitting for approval</div>
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Uploaded by:</label>
- ${tool.user.username}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Date uploaded:</label>
- ${time_ago( tool.create_time )}
- <div style="clear: both"></div>
- </div>
- </div>
- </div>
- <p/>
- <div class="toolForm">
- <div class="toolFormTitle">Manage categories</div>
- <div class="toolFormBody">
- <div class="form-row">
- <div style="float: left; margin-right: 10px;">
- <label>Categories associated with '${tool.name}'</label>
- ${render_select( "in_categories", in_categories )}<br/>
- <input type="submit" id="categories_remove_button" value=">>"/>
- </div>
- <div>
- <label>Categories not associated with '${tool.name}'</label>
- ${render_select( "out_categories", out_categories )}<br/>
- <input type="submit" id="categories_add_button" value="<<"/>
- </div>
- </div>
- <div class="form-row">
- <input type="submit" id="edit_tool_button" name="edit_tool_button" value="Save"/>
- </div>
- </div>
- </div>
- <p/>
- %if tool.is_new or tool.is_rejected:
- <div class="toolForm">
- <div class="toolFormTitle">Get approval for publishing</div>
- <div class="toolFormBody">
- <div class="form-row">
- <input type="submit" name="approval_button" id="approval_button" value="Submit for approval" onClick="return confirmSubmit()" />
- </div>
- <div class="form-row">
- <div class="toolParamHelp" style="clear: both;">
- Tools must be approved before they are made available to others in the community. After you have submitted
- your tool to be published, you will no longer be able to modify it, so make sure the information above is
- correct before submitting for approval.
- </div>
- </div>
- </div>
- </div>
- %endif
- </form>
-%else:
- ${render_msg( "You are not allowed to edit this tool", "error" )}
-%endif
--- a/templates/webapps/community/tool/grid.mako Thu Jun 02 14:18:34 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<%inherit file="/grid_base.mako"/>
--- a/templates/webapps/community/tool/help.mako Thu Jun 02 14:18:34 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-<%namespace file="/message.mako" import="render_msg" />
-
-<%!
- def inherit(context):
- if context.get('use_panels'):
- return '/webapps/community/base_panels.mako'
- else:
- return '/base.mako'
-%>
-<%inherit file="${inherit(context)}"/>
-
-<%def name="title()">Tool Help</%def>
-
-<h2>Tool Help</h2>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<p/>
-<div class="toolFormTitle">Creating an archive containing a tool or a suite of tools</div>
-<p>
- A tool or tool suite archive is a tar-format file (bzipped or gzipped tar are valid)
- containing all the files necessary to load the tool(s) into a Galaxy instance.
-</p>
-<h3>Tool Suite Archive</h3>
-<p>
- A tools suite must include a file named <code>suite_config.xml</code> which provides information about the id, name,
- version and description of the tool suite, as well as the id, name, version and description of each tool
- in the suite. Here is an example <code>suite_config.xml</code> file.
-</p>
-<p>
-<pre>
- <suite id="lastz_toolsuite" name="Suite of Lastz tools" version="1.0.0">
- <description>This suite contains all of my Lastz tools for Galaxy</description>
- <tool id="lastz_wrapper_2" name="Lastz" version="1.1.0">
- <description> map short reads against reference sequence</description>
- </tool>
- <tool id="lastz_paired_reads_wrapper" name="Lastz paired reads" version="1.0.0">
- <description> map short paired reads against reference sequence</description>
- </tool>
- </suite>
-</pre>
-</p>
-</p>
-<p>
- New versions of the suite can be uploaded, replacing an older version of the suite, but the version attribute
- of the <suite> tag must be altered the same way that the version attribute of a single tool config must be altered
- if uploading a new version of a tool.
-</p>
-<p>
- The id, name and version attributes of each <tool> tag in the <code>suite_config.xml</code> file must exactly match the same
- attributes in each associated tool config in the archive or you will not be allowed to upload the archive.
-</p>
-<p>
- In addition to the <code>suite_config.xml</code> file, the archive must include all
- <a href="http://bitbucket.org/galaxy/galaxy-central/wiki/ToolConfigSyntax" target="_blank">tool config files</a>,
- executables, functional test data (if your tool config includes functional tests) and other files needed for each
- of the tools in your suite to function within Galaxy. See the information about single tool archives below for
- additional hints to enable ease-of-use when others download your suite of tools.
-</p>
-<p>
- For example, to package the above Lastz suite of tools:
-<pre>
- user@host:~% tar jcvf ~/Desktop/galaxy_lastz_toolsuite.tar.bz2 lastzsuite
- lastzsuite/
- lastzsuite/README
- lastzsuite/suite_config.xml
- lastzsuite/lastz_paired_reads_wrapper.py
- lastzsuite/lastz_paired_reads_wrapper.xml
- lastzsuite/lastz_wrapper.py
- lastzsuite/lastz_wrapper.xml
- lastzsuite/lastz-distrib-1.02.00/
- lastzsuite/lastz-distrib-1.02.00/src/
- lastzsuite/lastz-distrib-1.02.00/src/Makefile
- lastzsuite/lastz-distrib-1.02.00/src/version.mak
- lastzsuite/lastz-distrib-1.02.00/src/lastz.c
- lastzsuite/lastz-distrib-1.02.00/src/lastz.h
- ...
-</pre>
- ~/Desktop/galaxy_lastz_tool.tar.bz2 is now ready to be uploaded.
-</p>
-<h3>Single Tool Archive</h3>
-<p>
- A single tool archive must include a
- <a href="http://bitbucket.org/galaxy/galaxy-central/wiki/ToolConfigSyntax" target="_blank">tool config file</a>
- and will probably also include a tool script. If any steps are necessary to install your tool beyond the basic
- instructions below, include a README file to provide details. If the tool (or parts of it) are written in C,
- the source code can be included (or put links to the source in the README). Do not include pre-compiled binaries
- without source since Galaxy is run on a wide variety of platforms. Also, if you are only wrapping or providing a
- Galaxy config for a tool that is not your own, be sure the license allows for redistribution before including any
- part of that tool in the archive.
-</p>
-<p>
- There are no requirements about the directory structure inside the archive, but for ease of use it's generally
- a good idea to put everything inside a sub-directory, instead of directly at the top level.
-</p>
-<p>
- For example, to package the Lastz tool's config file, Galaxy wrapper, and the C source:
-<pre>
- user@host:~% tar jcvf ~/Desktop/galaxy_lastz_tool.tar.bz2 lastz
- lastz/
- lastz/README
- lastz/lastz_wrapper.py
- lastz/lastz_wrapper.xml
- lastz/lastz-distrib-1.02.00/
- lastz/lastz-distrib-1.02.00/src/
- lastz/lastz-distrib-1.02.00/src/Makefile
- lastz/lastz-distrib-1.02.00/src/version.mak
- lastz/lastz-distrib-1.02.00/src/lastz.c
- lastz/lastz-distrib-1.02.00/src/lastz.h
- ...
-</pre>
- ~/Desktop/galaxy_lastz_tool.tar.bz2 is now ready to be uploaded.
-</p>
-<h3>Editing Information, Categories, and Submitting For Approval</h3>
-<p>
- Simply uploading a tool to the Galaxy too shed will not allow other users to find and download your tool. It will
- need to be approved by an administrator before it appears in the tool list.
-</p>
-<p>
- After your archive has successfully uploaded, you will be redirected to the Edit Tool page. Provide a detailed
- description of what the tool does - this will be used by administrators to understand the tool before approving it
- for display on the site. Once approved, this information will be displayed to users who view your tool. In addition,
- the site administrators will have configured a number of categories with which you can associate your tool to make it
- easy to find by users looking to solve specific problems. Associate as many categories as are relevant to your tool.
- You may change the description and associated categories as often as you'd like until you click the "<strong>Submit for
- approval</strong>" button. Once submitted, the tool will be approved or rejected by an administrator. If the tool is
- rejected, you will see information about why it was rejected, and you can make appropriate changes to the archive and
- re-submit it for approval. When it is approved, your archive will be visible to everyone. At that point, the description
- and associated categories can only be changed by an administrator.
-</p>
-<p>
- When the tool has been approved or rejected, you may upload a new version by browsing to the tool's "View Tool" page,
- clicking the "Tool actions" menu in the upper right corner of the page, and selecting "Upload a new version" from the
- menu.
-</p>
-<hr/>
-<h3>Downloading and Installing Tools</h3>
-<p>
- A tool's download link will send you the tool archive. Once downloaded, unpack the tool on your local Galaxy instance's server:
-<pre>
- user@host:~% tar xvf galaxy_lastz_tool.tar
- ...
- user@host:~% tar zxvf galaxy_lastz_tool.tar.gz
- ...
- user@host:~% tar jxvf galaxy_lastz_tool.tar.bz2
- ...
-</pre>
- If the archive includes a README file, consult it for installation instructions. If not, follow these basic steps:
- <ol>
- <li>Create a directory under <code>galaxy_dist/tools/</code> to house downloaded tool(s).</li>
- <li>In the new directory, place the XML and any script file(s) which were contained in the archive.</li>
- <li>
- If the tool includes binaries, you'll need to copy them to a directory on your <code>$PATH</code>. If the tool depends on
- C binaries but does not come with them (only source), you'll need to compile the source first.
- </li>
- <li>Add the tool to <code>galaxy_dist/tool_conf.xml</code>.</li>
- <li>Restart your Galaxy server process.</li>
- </ol>
-</p>
-<p>
- In the near future, we plan to implement a more direct method to install tools via the Galaxy administrator user interface instead
- of placing files on the filesystem and manually managing the <code>tool_conf.xml</code> file.
-</p>
-
--- a/templates/webapps/community/tool/view_tool.mako Thu Jun 02 14:18:34 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,247 +0,0 @@
-<%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/webapps/community/common/common.mako" import="*" />
-
-<%
- from galaxy.web.framework.helpers import time_ago
- from urllib import quote_plus
-
- if cntrller in [ 'tool' ] and can_edit:
- menu_label = 'Edit information or submit for approval'
- else:
- menu_label = 'Edit information'
-%>
-
-<%!
- def inherit(context):
- if context.get('use_panels'):
- return '/webapps/community/base_panels.mako'
- else:
- return '/base.mako'
-%>
-<%inherit file="${inherit(context)}"/>
-
-<%def name="stylesheets()">
- ${parent.stylesheets()}
- ${h.css( "jquery.rating" )}
- <style type="text/css">
- ul.fileBrowser,
- ul.toolFile {
- margin-left: 0;
- padding-left: 0;
- list-style: none;
- }
- ul.fileBrowser {
- margin-left: 20px;
- }
- .fileBrowser li,
- .toolFile li {
- padding-left: 20px;
- background-repeat: no-repeat;
- background-position: 0;
- min-height: 20px;
- }
- .toolFile li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white_compressed.png' )} );
- }
- .fileBrowser li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white.png' )} );
- }
- </style>
-</%def>
-
-<%def name="javascripts()">
- ${parent.javascripts()}
- ${h.js( "jquery.rating" )}
-</%def>
-
-<%def name="title()">View Tool</%def>
-
-<h2>View Tool</h2>
-
-${tool.get_state_message()}
-<p/>
-
-<ul class="manage-table-actions">
- %if can_approve_or_reject:
- <li><a class="action-button" href="${h.url_for( controller='admin', action='set_tool_state', state=trans.model.Tool.states.APPROVED, id=trans.security.encode_id( tool.id ), cntrller=cntrller )}">Approve</a></li>
- <li><a class="action-button" href="${h.url_for( controller='admin', action='set_tool_state', state=trans.model.Tool.states.REJECTED, id=trans.security.encode_id( tool.id ), cntrller=cntrller )}">Reject</a></li>
- %endif
- <li><a class="action-button" id="tool-${tool.id}-popup" class="menubutton">Tool Actions</a></li>
- <div popupmenu="tool-${tool.id}-popup">
- %if can_edit:
- <a class="action-button" href="${h.url_for( controller='common', action='edit_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">${menu_label}</a>
- %endif
- <a class="action-button" href="${h.url_for( controller='common', action='view_tool_history', id=trans.security.encode_id( tool.id ), cntrller=cntrller )}">Tool history</a>
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='common', action='download_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">Download tool</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='common', action='rate_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">Rate tool</a>
- %endif
- %if can_delete:
- <a class="action-button" href="${h.url_for( controller='common', action='delete_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}" confirm="Are you sure you want to delete this tool?">Delete tool</a>
- %endif
- %if can_upload_new_version:
- <a class="action-button" href="${h.url_for( controller='common', action='upload_new_tool_version', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">Upload a new version</a>
- %endif
- %if can_purge:
- <li><a class="action-button" href="${h.url_for( controller='admin', action='purge_tool', id=trans.security.encode_id( tool.id ), cntrller=cntrller )}" confirm="Purging removes records from the database, are you sure you want to purge this tool?">Purge tool</a></li>
- %endif
- </div>
-</ul>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-%if can_view:
- %if tool.is_rejected:
- <div class="toolForm">
- <div class="toolFormTitle">Reason for rejection</div>
- <div class="toolFormBody">
- <div class="form-row">
- ${reason_for_rejection}
- <div style="clear: both"></div>
- </div>
- </div>
- </div>
- <p/>
- %endif
- <div class="toolForm">
- <div class="toolFormTitle">${tool.name}</div>
- <div class="toolFormBody">
- <div class="form-row">
- <label>Tool Id:</label>
- ${tool.tool_id}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Version:</label>
- ${tool.version}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Description:</label>
- ${tool.description}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>User Description:</label>
- %if tool.user_description:
- <pre>${tool.user_description}</pre>
- %endif
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Uploaded by:</label>
- ${tool.user.username}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Date uploaded:</label>
- ${time_ago( tool.create_time )}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Categories:</label>
- %if categories:
- <ul>
- %for category in categories:
- <li>${category.name}</li>
- %endfor
- </ul>
- %else:
- none set
- %endif
- <div style="clear: both"></div>
- </div>
- %if len( visible_versions ) > 1:
- <div class="form-row">
- <label>All Versions:</label>
- <ul>
- %for version in visible_versions:
- %if version == tool:
- <li><strong>${version.version} (this version)</strong></li>
- %else:
- <li><a href="${h.url_for( controller='common', action='view_tool', id=trans.app.security.encode_id( version.id ), cntrller=cntrller )}">${version.version}</a></li>
- %endif
- %endfor
- </ul>
- <div style="clear: both"></div>
- </div>
- %endif
- </div>
- </div>
- <p/>
- <div class="toolForm">
- <div class="toolFormTitle">Tool Contents</div>
- <div class="toolFormBody">
- <div class="form-row">
- <ul class="toolFile">
- <li><a href="${h.url_for( controller='common', action='download_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">${tool.download_file_name}</a></li>
- <ul class="fileBrowser">
- %for name in tool_file_contents:
- <li><a href="${h.url_for( controller='tool', action='view_tool_file', id=trans.app.security.encode_id( tool.id ), file_name=quote_plus( name ) )}">${name}</a></li>
- %endfor
- </ul>
- </ul>
- </div>
- </div>
- </div>
- <p/>
- %if tool.ratings:
- <div class="toolForm">
- <div class="toolFormTitle">Rating</div>
- <div class="toolFormBody">
- <div class="form-row">
- <label>Times Rated:</label>
- ${num_ratings}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Average Rating:</label>
- ${render_star_rating( 'avg_rating', avg_rating, disabled=True )}
- <div style="clear: both"></div>
- </div>
- </div>
- </div>
- <p/>
- <div class="toolForm">
- <div class="toolFormBody">
- %if display_reviews:
- <div class="form-row">
- <a href="${h.url_for( controller='common', action='view_tool', id=trans.security.encode_id( tool.id ), cntrller=cntrller, display_reviews=False )}"><label>Hide Reviews</label></a>
- </div>
- <table class="grid">
- <thead>
- <tr>
- <th>Rating</th>
- <th>Comments</th>
- <th>Reviewed</th>
- <th>User</th>
- </tr>
- </thead>
- <% count = 0 %>
- %for review in tool.ratings:
- <%
- count += 1
- name = 'rating%d' % count
- %>
- <tr>
- <td>${render_star_rating( name, review.rating, disabled=True )}</td>
- <td>${review.comment}</td>
- <td>${time_ago( review.update_time )}</td>
- <td>${review.user.username}</td>
- </tr>
- %endfor
- </table>
- %else:
- <div class="form-row">
- <a href="${h.url_for( controller='common', action='view_tool', id=trans.security.encode_id( tool.id ), cntrller=cntrller, display_reviews=True )}"><label>Display Reviews</label></a>
- </div>
- %endif
- </div>
- </div>
- %endif
- <p/>
-%endif
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: dan: Provide an error message when trying to directly view a directory in extra_files_path.
by Bitbucket 02 Jun '11
by Bitbucket 02 Jun '11
02 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/4618be57481b/
changeset: 4618be57481b
branches:
user: dan
date: 2011-06-02 20:18:34
summary: Provide an error message when trying to directly view a directory in extra_files_path.
affected #: 1 file (207 bytes)
--- a/lib/galaxy/web/controllers/dataset.py Thu Jun 02 13:10:28 2011 -0400
+++ b/lib/galaxy/web/controllers/dataset.py Thu Jun 02 14:18:34 2011 -0400
@@ -348,17 +348,18 @@
# For files in extra_files_path
file_path = os.path.join( data.extra_files_path, filename )
if os.path.exists( file_path ):
+ if os.path.isdir( file_path ):
+ return trans.show_error_message( "Directory listing is not allowed." ) #TODO: Reconsider allowing listing of directories?
mime, encoding = mimetypes.guess_type( file_path )
if not mime:
try:
mime = trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( file_path )[-1] )
except:
mime = "text/plain"
-
trans.response.set_content_type( mime )
return open( file_path )
else:
- return "Could not find '%s' on the extra files path %s." % (filename,file_path)
+ return trans.show_error_message( "Could not find '%s' on the extra files path %s." % ( filename, file_path ) )
mime = trans.app.datatypes_registry.get_mimetype_by_extension( data.extension.lower() )
trans.response.set_content_type(mime)
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: natefoo: Fix the race condition of the upload tool's outputs not being created before the output size check occurs. Thanks Tao Liu.
by Bitbucket 02 Jun '11
by Bitbucket 02 Jun '11
02 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/7e1dca8036b8/
changeset: 7e1dca8036b8
branches:
user: natefoo
date: 2011-06-02 19:10:28
summary: Fix the race condition of the upload tool's outputs not being created before the output size check occurs. Thanks Tao Liu.
affected #: 1 file (196 bytes)
--- a/lib/galaxy/tools/actions/upload_common.py Thu Jun 02 12:11:53 2011 -0400
+++ b/lib/galaxy/tools/actions/upload_common.py Thu Jun 02 13:10:28 2011 -0400
@@ -322,9 +322,13 @@
if folder:
for i, dataset in enumerate( data_list ):
job.add_output_library_dataset( 'output%i' % i, dataset )
+ # Create an empty file immediately
+ open( dataset.file_name, "w" ).close()
else:
for i, dataset in enumerate( data_list ):
job.add_output_dataset( 'output%i' % i, dataset )
+ # Create an empty file immediately
+ open( dataset.file_name, "w" ).close()
job.state = job.states.NEW
trans.sa_session.add( job )
trans.sa_session.flush()
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: natefoo: 'fields' is apparently reserved in MySQL 4, fix migration scripts that use it unaliased. Thanks John Eppley.
by Bitbucket 02 Jun '11
by Bitbucket 02 Jun '11
02 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/b6689fb6532e/
changeset: b6689fb6532e
branches:
user: natefoo
date: 2011-06-02 18:11:53
summary: 'fields' is apparently reserved in MySQL 4, fix migration scripts that use it unaliased. Thanks John Eppley.
affected #: 2 files (38 bytes)
--- a/lib/galaxy/model/migrate/versions/0065_add_name_to_form_fields_and_values.py Thu Jun 02 11:46:49 2011 -0400
+++ b/lib/galaxy/model/migrate/versions/0065_add_name_to_form_fields_and_values.py Thu Jun 02 12:11:53 2011 -0400
@@ -39,7 +39,7 @@
return ''
# Go through the entire table and add a 'name' attribute for each field
# in the list of fields for each form definition
- cmd = "SELECT id, fields FROM form_definition"
+ cmd = "SELECT f.id, f.fields FROM form_definition AS f"
result = db_session.execute( cmd )
for row in result:
form_definition_id = row[0]
@@ -53,7 +53,7 @@
field[ 'helptext' ] = field[ 'helptext' ].replace("'", "''").replace('"', "")
field[ 'label' ] = field[ 'label' ].replace("'", "''")
fields_json = to_json_string( fields_list )
- cmd = "UPDATE form_definition SET fields='%s' WHERE id=%i" %( fields_json, form_definition_id )
+ cmd = "UPDATE form_definition AS f SET f.fields='%s' WHERE f.id=%i" %( fields_json, form_definition_id )
db_session.execute( cmd )
# replace the values list in the content field of the form_values table with a name:value dict
cmd = "SELECT form_values.id, form_values.content, form_definition.fields" \
@@ -112,7 +112,7 @@
cmd = "UPDATE form_values SET content='%s' WHERE id=%i" %( to_json_string( values_list ), form_values_id )
db_session.execute( cmd )
# remove name attribute from the field column of the form_definition table
- cmd = "SELECT id, fields FROM form_definition"
+ cmd = "SELECT f.id, f.fields FROM form_definition AS f"
result = db_session.execute( cmd )
for row in result:
form_definition_id = row[0]
@@ -124,5 +124,5 @@
for index, field in enumerate( fields_list ):
if field.has_key( 'name' ):
del field[ 'name' ]
- cmd = "UPDATE form_definition SET fields='%s' WHERE id=%i" %( to_json_string( fields_list ), form_definition_id )
+ cmd = "UPDATE form_definition AS f SET f.fields='%s' WHERE id=%i" %( to_json_string( fields_list ), form_definition_id )
db_session.execute( cmd )
--- a/lib/galaxy/model/migrate/versions/0076_fix_form_values_data_corruption.py Thu Jun 02 11:46:49 2011 -0400
+++ b/lib/galaxy/model/migrate/versions/0076_fix_form_values_data_corruption.py Thu Jun 02 12:11:53 2011 -0400
@@ -32,7 +32,7 @@
def upgrade():
print __doc__
metadata.reflect()
- cmd = "SELECT form_values.id as id, form_values.content as field_values, form_definition.fields as fields " \
+ cmd = "SELECT form_values.id as id, form_values.content as field_values, form_definition.fields as fdfields " \
+ " FROM form_definition, form_values " \
+ " WHERE form_values.form_definition_id=form_definition.id " \
+ " ORDER BY form_values.id"
@@ -46,7 +46,7 @@
except Exception, e:
corrupted_rows = corrupted_rows + 1
# content field is corrupted
- fields_list = from_json_string( _sniffnfix_pg9_hex( str( row['fields'] ) ) )
+ fields_list = from_json_string( _sniffnfix_pg9_hex( str( row['fdfields'] ) ) )
field_values_str = _sniffnfix_pg9_hex( str( row['field_values'] ) )
try:
#Encoding errors? Just to be safe.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: dan: Import patch contributed by Jim Johnson that supports sub directories in extra_files_path for displaying and downloading.
by Bitbucket 02 Jun '11
by Bitbucket 02 Jun '11
02 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/b9fdb88da530/
changeset: b9fdb88da530
branches:
user: dan
date: 2011-06-02 17:46:49
summary: Import patch contributed by Jim Johnson that supports sub directories in extra_files_path for displaying and downloading.
"Numerous applications create html files with a directory hierarchy. I\'m including a patch support the display and download of datasets that include subdirs in their extra_files_path."
affected #: 2 files (263 bytes)
--- a/lib/galaxy/web/buildapp.py Thu Jun 02 11:40:06 2011 -0400
+++ b/lib/galaxy/web/buildapp.py Thu Jun 02 11:46:49 2011 -0400
@@ -94,6 +94,8 @@
webapp.add_route( '/async/:tool_id/:data_id/:data_secret', controller='async', action='index', tool_id=None, data_id=None, data_secret=None )
webapp.add_route( '/:controller/:action', action='index' )
webapp.add_route( '/:action', controller='root', action='index' )
+ # allow for subdirectories in extra_files_path
+ webapp.add_route( '/datasets/:dataset_id/display/{filename:.+?}', controller='dataset', action='display', dataset_id=None, filename=None)
webapp.add_route( '/datasets/:dataset_id/:action/:filename', controller='dataset', action='index', dataset_id=None, filename=None)
webapp.add_route( '/display_application/:dataset_id/:app_name/:link_name/:user_id/:app_action/:action_param', controller='dataset', action='display_application', dataset_id=None, user_id=None, app_name = None, link_name = None, app_action = None, action_param = None )
webapp.add_route( '/u/:username/d/:slug', controller='dataset', action='display_by_username_and_slug' )
--- a/lib/galaxy/web/controllers/dataset.py Thu Jun 02 11:40:06 2011 -0400
+++ b/lib/galaxy/web/controllers/dataset.py Thu Jun 02 11:46:49 2011 -0400
@@ -267,17 +267,18 @@
log.exception( "Unable to add composite parent %s to temporary library download archive" % data.file_name)
msg = "Unable to create archive for download, please report this error"
messagetype = 'error'
- flist = glob.glob(os.path.join(efp,'*.*')) # glob returns full paths
- for fpath in flist:
- efp,fname = os.path.split(fpath)
- try:
- archive.add( fpath,fname )
- except IOError:
- error = True
- log.exception( "Unable to add %s to temporary library download archive" % fname)
- msg = "Unable to create archive for download, please report this error"
- messagetype = 'error'
- continue
+ for root, dirs, files in os.walk(efp):
+ for fname in files:
+ fpath = os.path.join(root,fname)
+ rpath = os.path.relpath(fpath,efp)
+ try:
+ archive.add( fpath,rpath )
+ except IOError:
+ error = True
+ log.exception( "Unable to add %s to temporary library download archive" % rpath)
+ msg = "Unable to create archive for download, please report this error"
+ messagetype = 'error'
+ continue
if not error:
if params.do_action == 'zip':
archive.close()
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: natefoo: Another fix for uploading datasets to a library without a history.
by Bitbucket 02 Jun '11
by Bitbucket 02 Jun '11
02 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/83103cff8757/
changeset: 83103cff8757
branches:
user: natefoo
date: 2011-06-02 17:40:06
summary: Another fix for uploading datasets to a library without a history.
affected #: 1 file (160 bytes)
--- a/lib/galaxy/tools/parameters/basic.py Thu Jun 02 11:06:08 2011 -0400
+++ b/lib/galaxy/tools/parameters/basic.py Thu Jun 02 11:40:06 2011 -0400
@@ -801,10 +801,15 @@
hg17
"""
def get_options( self, trans, other_values ):
- last_used_build = trans.history.genome_build
- for dbkey, build_name in trans.db_builds:
- yield build_name, dbkey, ( dbkey == last_used_build )
+ if not trans.history:
+ yield 'unspecified', '?', False
+ else:
+ last_used_build = trans.history.genome_build
+ for dbkey, build_name in trans.db_builds:
+ yield build_name, dbkey, ( dbkey == last_used_build )
def get_legal_values( self, trans, other_values ):
+ if not trans.history:
+ return set( '?' )
return set( dbkey for dbkey, _ in trans.db_builds )
class ColumnListParameter( SelectToolParameter ):
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: natefoo: Fix for library upload when there is no current history.
by Bitbucket 02 Jun '11
by Bitbucket 02 Jun '11
02 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/1f2870dc3ab0/
changeset: 1f2870dc3ab0
branches:
user: natefoo
date: 2011-06-02 17:06:08
summary: Fix for library upload when there is no current history.
affected #: 1 file (36 bytes)
--- a/lib/galaxy/web/controllers/library_common.py Wed Jun 01 16:27:28 2011 -0400
+++ b/lib/galaxy/web/controllers/library_common.py Thu Jun 02 11:06:08 2011 -0400
@@ -905,7 +905,8 @@
dbkeys = get_dbkey_options( last_used_build )
# Send the current history to the form to enable importing datasets from history to library
history = trans.get_history()
- trans.sa_session.refresh( history )
+ if history is not None:
+ trans.sa_session.refresh( history )
if upload_option == 'upload_file' and trans.app.config.nginx_upload_path:
# If we're using nginx upload, override the form action -
# url_for is intentionally not used on the base URL here -
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: natefoo: Set a catchall content-type (application/octet-stream) on metadata file downloads so Safari doesn't consider them to be html.
by Bitbucket 01 Jun '11
by Bitbucket 01 Jun '11
01 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/8d5850e45538/
changeset: 8d5850e45538
branches:
user: natefoo
date: 2011-06-01 22:27:28
summary: Set a catchall content-type (application/octet-stream) on metadata file downloads so Safari doesn't consider them to be html.
affected #: 1 file (76 bytes)
--- a/lib/galaxy/web/controllers/dataset.py Wed Jun 01 16:21:12 2011 -0400
+++ b/lib/galaxy/web/controllers/dataset.py Wed Jun 01 16:27:28 2011 -0400
@@ -316,6 +316,7 @@
valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
fname = ''.join(c in valid_chars and c or '_' for c in data.name)[0:150]
+ trans.response.headers["Content-Type"] = "application/octet-stream"
trans.response.headers["Content-Disposition"] = "attachment; filename=Galaxy%s-[%s].%s" % (data.hid, fname, metadata_type)
return open(data.metadata.get(metadata_type).file_name)
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

01 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/cf7ef2464568/
changeset: cf7ef2464568
branches:
user: greg
date: 2011-06-01 22:21:12
summary: Fix the ToolParamSanitizer unit test. Since mercurial imports locale.getpreferredencoding(), which is part of the Python stdlib, the behavior of python strings is re-sorted, so we have to sort them back...
affected #: 1 file (72 bytes)
--- a/lib/galaxy/tools/parameters/sanitize.py Wed Jun 01 15:47:04 2011 -0400
+++ b/lib/galaxy/tools/parameters/sanitize.py Wed Jun 01 16:21:12 2011 -0400
@@ -19,7 +19,7 @@
... <valid initial="string.letters"/>
... </sanitizer>
... ''' ) )
- >>> sanitizer.sanitize_param( string.printable ) == string.letters
+ >>> sanitizer.sanitize_param( ''.join( sorted( [ c for c in string.printable ] ) ) ) == ''.join( sorted( [ c for c in string.letters ] ) )
True
>>> slash = chr( 92 )
>>> sanitizer = ToolParameterSanitizer.from_element( XML(
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: greg: Fixes for editing role name, descriptionn, and renaming groups. Resolves issue #539.
by Bitbucket 01 Jun '11
by Bitbucket 01 Jun '11
01 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/c1d5b67e2090/
changeset: c1d5b67e2090
branches:
user: greg
date: 2011-06-01 21:47:04
summary: Fixes for editing role name, descriptionn, and renaming groups. Resolves issue #539.
affected #: 2 files (479 bytes)
--- a/lib/galaxy/web/base/controller.py Wed Jun 01 15:20:43 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Wed Jun 01 15:47:04 2011 -0400
@@ -1278,20 +1278,23 @@
if not new_name:
message = 'Enter a valid name'
status='error'
- elif trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.name==new_name ).first():
- message = 'A role with that name already exists'
- status = 'error'
else:
- role.name = new_name
- role.description = new_description
- trans.sa_session.add( role )
- trans.sa_session.flush()
- message = "Role '%s' has been renamed to '%s'" % ( old_name, new_name )
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='roles',
- webapp=webapp,
- message=util.sanitize_text( message ),
- status='done' ) )
+ existing_role = trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.name==new_name ).first()
+ if existing_role and existing_role.id != role.id:
+ message = 'A role with that name already exists'
+ status = 'error'
+ else:
+ if not ( role.name == new_name and role.description == new_description ):
+ role.name = new_name
+ role.description = new_description
+ trans.sa_session.add( role )
+ trans.sa_session.flush()
+ message = "Role '%s' has been renamed to '%s'" % ( old_name, new_name )
+ return trans.response.send_redirect( web.url_for( controller='admin',
+ action='roles',
+ webapp=webapp,
+ message=util.sanitize_text( message ),
+ status='done' ) )
return trans.fill_template( '/admin/dataset_security/role/role_rename.mako',
role=role,
webapp=webapp,
@@ -1556,19 +1559,22 @@
if not new_name:
message = 'Enter a valid name'
status = 'error'
- elif trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.name==new_name ).first():
- message = 'A group with that name already exists'
- status = 'error'
else:
- group.name = new_name
- trans.sa_session.add( group )
- trans.sa_session.flush()
- message = "Group '%s' has been renamed to '%s'" % ( old_name, new_name )
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='groups',
- webapp=webapp,
- message=util.sanitize_text( message ),
- status='done' ) )
+ existing_group = trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.name==new_name ).first()
+ if existing_group and existing_group.id != group.id:
+ message = 'A group with that name already exists'
+ status = 'error'
+ else:
+ if group.name != new_name:
+ group.name = new_name
+ trans.sa_session.add( group )
+ trans.sa_session.flush()
+ message = "Group '%s' has been renamed to '%s'" % ( old_name, new_name )
+ return trans.response.send_redirect( web.url_for( controller='admin',
+ action='groups',
+ webapp=webapp,
+ message=util.sanitize_text( message ),
+ status='done' ) )
return trans.fill_template( '/admin/dataset_security/group/group_rename.mako',
group=group,
webapp=webapp,
--- a/lib/galaxy/web/controllers/admin.py Wed Jun 01 15:20:43 2011 -0400
+++ b/lib/galaxy/web/controllers/admin.py Wed Jun 01 15:47:04 2011 -0400
@@ -169,7 +169,7 @@
global_actions = [
grids.GridAction( "Add new role", dict( controller='admin', action='roles', operation='create' ) )
]
- operations = [ grids.GridOperation( "Rename",
+ operations = [ grids.GridOperation( "Edit",
condition=( lambda item: not item.deleted ),
allow_multiple=False,
url_args=dict( webapp="galaxy", action="rename_role" ) ),
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/3297ec86d657/
changeset: 3297ec86d657
branches:
user: greg
date: 2011-06-01 21:20:43
summary: Several data library bug fixes:
- Determiining if an accessible dataset exists somewhere in the data library hierarchy now works all the time ( I believe ). It used to work most of the time, but under corner conditions, it would break.
- When importing dataset from a history into a data library, the dataset permissions are now correctly applied to the library dataset. The DATASET_MANAGE_PERMISSIONS permission is a spoecial case in that if it exists on the dataset, the LIBRARY_MANAGE permission must be applied to the library dataset.
- Fix for message display and db flushing when importing library dataset into a history.
- Do not render the folder pop-up menu option for selecting library dataset to import into histories if the folder does not contain any accessible library datasets.
affected #: 3 files (2.6 KB)
--- a/lib/galaxy/security/__init__.py Wed Jun 01 15:12:12 2011 -0400
+++ b/lib/galaxy/security/__init__.py Wed Jun 01 15:20:43 2011 -0400
@@ -287,8 +287,12 @@
if self.can_access_library_item( roles, library_dataset, user ):
return True
if search_downward:
- for folder in folder.active_folders:
- return self.has_accessible_library_datasets( trans, folder, user, roles, search_downward=search_downward )
+ return self.__active_folders_have_accessible_library_datasets( trans, folder, user, roles )
+ return False
+ def __active_folders_have_accessible_library_datasets( self, trans, folder, user, roles ):
+ for active_folder in folder.active_folders:
+ if self.has_accessible_library_datasets( trans, active_folder, user, roles ):
+ return True
return False
def can_access_library_item( self, roles, item, user ):
if type( item ) == self.model.Library:
--- a/lib/galaxy/web/controllers/library_common.py Wed Jun 01 15:12:12 2011 -0400
+++ b/lib/galaxy/web/controllers/library_common.py Wed Jun 01 15:20:43 2011 -0400
@@ -11,6 +11,7 @@
from galaxy.web.form_builder import AddressField, CheckboxField, SelectField, TextArea, TextField, WorkflowField, WorkflowMappingField, HistoryField
import logging, tempfile, zipfile, tarfile, os, sys, operator
from galaxy.eggs import require
+from galaxy.security import Action
# Whoosh is compatible with Python 2.5+ Try to import Whoosh and set flag to indicate whether tool search is enabled.
try:
require( "Whoosh" )
@@ -829,7 +830,7 @@
**kwd )
if created_outputs_dict:
if cntrller == 'api':
- # created_outputs_dict can only ever be a string if cntrller == 'api'
+ # created_outputs_dict can be a string only if cntrller == 'api'
if type( created_outputs_dict ) == str:
return 400, created_outputs_dict
return 200, created_outputs_dict
@@ -1211,6 +1212,27 @@
# LDDA and LibraryDataset.
trans.app.security_agent.copy_library_permissions( folder, ldda )
trans.app.security_agent.copy_library_permissions( folder, ldda.library_dataset )
+ # Make sure to apply any defined dataset permissions, allowing the permissions inherited from the folder to
+ # over-ride the same permissions on the dataset, if they exist.
+ dataset_permissions_dict = trans.app.security_agent.get_permissions( hda.dataset )
+ current_library_dataset_actions = [ permission.action for permission in ldda.library_dataset.actions ]
+ # The DATASET_MANAGE_PERMISSIONS permission on a dataset is a special case because if
+ # it exists, then we need to apply the LIBRARY_MANAGE permission to the library dataset.
+ dataset_manage_permissions_action = trans.app.security_agent.get_action( 'DATASET_MANAGE_PERMISSIONS' ).action
+ flush_needed = False
+ for action, roles in dataset_permissions_dict.items():
+ if isinstance( action, Action ):
+ action = action.action
+ if action == dataset_manage_permissions_action:
+ # Apply the LIBRARY_MANAGE permission to the library dataset.
+ action = trans.app.security_agent.get_action( 'LIBRARY_MANAGE' ).action
+ # Allow the permissions inherited from the folder to over-ride the same permissions on the dataset.
+ if action not in current_library_dataset_actions:
+ for ldp in [ trans.model.LibraryDatasetPermissions( action, ldda.library_dataset, role ) for role in roles ]:
+ trans.sa_session.add( ldp )
+ flush_needed = True
+ if flush_needed:
+ trans.sa_session.flush()
# Permissions must be the same on the LibraryDatasetDatasetAssociation and the associated LibraryDataset
trans.app.security_agent.copy_library_permissions( ldda.library_dataset, ldda )
if created_ldda_ids:
@@ -1605,7 +1627,7 @@
valid_lddas = []
invalid_lddas = []
for ldda in lddas:
- if trans.app.security_agent.can_manage_library_item( current_user_roles, ldda ):
+ if is_admin or trans.app.security_agent.can_manage_library_item( current_user_roles, ldda ):
valid_lddas.append( ldda )
valid_ldda_ids.append( ldda.id )
else:
@@ -1634,7 +1656,7 @@
valid_lddas = []
invalid_lddas = []
for ldda in lddas:
- if trans.app.security_agent.can_modify_library_item( current_user_roles, ldda ):
+ if is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, ldda ):
valid_lddas.append( ldda )
else:
invalid_lddas.append( ldda )
@@ -1859,6 +1881,7 @@
if len( target_histories ) != len( target_history_ids ):
message += "You do not have permission to add datasets to %i requested histories. " % ( len( target_history_ids ) - len( target_histories ) )
status = 'error'
+ flush_needed = False
for ldda in map( trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get, ldda_ids ):
if ldda is None:
message += "You tried to import a dataset that does not exist. "
@@ -1875,15 +1898,18 @@
else:
for target_history in target_histories:
hda = ldda.to_history_dataset_association( target_history=target_history, add_to_history=True )
- trans.sa_session.flush()
- hist_names_str = ", ".join( [ target_history.name for target_history in target_histories ] )
- num_source = len( ldda_ids ) - invalid_datasets
- num_target = len( target_histories )
- message = "%i %s imported into %i %s: %s" % ( num_source,
- inflector.cond_plural( num_source, "dataset" ),
- num_target,
- inflector.cond_plural( num_target, "history" ),
- hist_names_str )
+ if not flush_needed:
+ flush_needed = True
+ if flush_needed:
+ trans.sa_session.flush()
+ hist_names_str = ", ".join( [ target_history.name for target_history in target_histories ] )
+ num_source = len( ldda_ids ) - invalid_datasets
+ num_target = len( target_histories )
+ message += "%i %s imported into %i %s: %s" % ( num_source,
+ inflector.cond_plural( num_source, "dataset" ),
+ num_target,
+ inflector.cond_plural( num_target, "history" ),
+ hist_names_str )
trans.sa_session.refresh( current_history )
current_user_roles = trans.get_current_user_roles()
source_lddas = []
--- a/templates/library/common/browse_library.mako Wed Jun 01 15:12:12 2011 -0400
+++ b/templates/library/common/browse_library.mako Wed Jun 01 15:20:43 2011 -0400
@@ -314,6 +314,7 @@
from galaxy.web.controllers.library_common import active_folders, active_folders_and_library_datasets, activatable_folders_and_library_datasets, branch_deleted
is_admin = trans.user_is_admin() and cntrller == 'library_admin'
+ has_accessible_library_datasets = trans.app.security_agent.has_accessible_library_datasets( trans, folder, trans.user, current_user_roles, search_downward=False )
if root_folder:
pad = folder_pad
@@ -380,7 +381,7 @@
<a class="action-button" href="${h.url_for( controller='library_common', action='create_folder', cntrller=cntrller, parent_id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add sub-folder</a>
%endif
%if not branch_deleted( folder ):
- %if self.has_accessible_datasets:
+ %if has_accessible_library_datasets:
<a class="action-button" href="${h.url_for( controller='library_common', action='import_datasets_to_histories', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Select datasets for import into selected histories</a>
%endif
%if can_modify:
@@ -488,6 +489,7 @@
form_type = trans.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE
self.has_accessible_datasets = trans.app.security_agent.has_accessible_library_datasets( trans, library.root_folder, trans.user, current_user_roles )
+ root_folder_has_accessible_library_datasets = trans.app.security_agent.has_accessible_library_datasets( trans, library.root_folder, trans.user, current_user_roles, search_downward=False )
has_accessible_folders = is_admin or trans.app.security_agent.has_accessible_folders( trans, library.root_folder, trans.user, current_user_roles )
tracked_datasets = {}
@@ -500,7 +502,7 @@
def __str__( self ):
return str( self.count )
%>
-
+
<h2>Data Library “${library.name}”</h2><ul class="manage-table-actions">
@@ -534,7 +536,7 @@
%endif
<a class="action-button" href="${h.url_for( controller='library_common', action='library_permissions', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit permissions</a>
%endif
- %if self.has_accessible_datasets:
+ %if root_folder_has_accessible_library_datasets:
<a class="action-button" href="${h.url_for( controller='library_common', action='import_datasets_to_histories', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( library.root_folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Select datasets for import into selected histories</a>
%endif
%elif can_modify and not library.purged:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: natefoo: Fix the user create/login links in the FTP upload form
by Bitbucket 01 Jun '11
by Bitbucket 01 Jun '11
01 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/c1468d790495/
changeset: c1468d790495
branches:
user: natefoo
date: 2011-06-01 21:12:12
summary: Fix the user create/login links in the FTP upload form
affected #: 1 file (34 bytes)
--- a/lib/galaxy/web/form_builder.py Wed Jun 01 11:40:38 2011 -0400
+++ b/lib/galaxy/web/form_builder.py Wed Jun 01 15:12:12 2011 -0400
@@ -185,7 +185,7 @@
def get_html( self, prefix="" ):
rval = FTPFileField.thead
if self.dir is None:
- rval += '<tr><td colspan="3"><em>Please <a href="%s">create</a> or <a href="%s">log in to</a> a Galaxy account to view files uploaded via FTP.</em></td></tr>' % ( url_for( controller='user', action='create', referer=url_for( controller='root' ) ), url_for( controller='user', action='login', referer=url_for( controller='root' ) ) )
+ rval += '<tr><td colspan="3"><em>Please <a href="%s">create</a> or <a href="%s">log in to</a> a Galaxy account to view files uploaded via FTP.</em></td></tr>' % ( url_for( controller='user', action='create', cntrller='user', referer=url_for( controller='root' ) ), url_for( controller='user', action='login', cntrller='user', referer=url_for( controller='root' ) ) )
elif not os.path.exists( self.dir ):
rval += '<tr><td colspan="3"><em>Your FTP upload directory contains no files.</em></td></tr>'
else:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

01 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/0a186b0aa953/
changeset: 0a186b0aa953
branches:
user: dan
date: 2011-06-01 17:40:38
summary: Minor reformatting for 5609:f530dbdde1f5
affected #: 1 file (0 bytes)
--- a/lib/galaxy_utils/sequence/vcf.py Wed Jun 01 11:29:07 2011 -0400
+++ b/lib/galaxy_utils/sequence/vcf.py Wed Jun 01 11:40:38 2011 -0400
@@ -2,7 +2,7 @@
#See: http://1000genomes.org/wiki/doku.php?id=1000_genomes:analysis:vcf3.3
#See: http://1000genomes.org/wiki/doku.php?id=1000_genomes:analysis:variant_call_…
-NOT_A_NUMBER = float( 'NaN ')
+NOT_A_NUMBER = float( 'NaN' )
class VariantCall( object ):
version = None
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: dan: Allow VCF parser to accept unknown values for QUAL field.
by Bitbucket 01 Jun '11
by Bitbucket 01 Jun '11
01 Jun '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/f530dbdde1f5/
changeset: f530dbdde1f5
branches:
user: dan
date: 2011-06-01 17:29:07
summary: Allow VCF parser to accept unknown values for QUAL field.
affected #: 1 file (139 bytes)
--- a/lib/galaxy_utils/sequence/vcf.py Tue May 31 12:03:52 2011 -0400
+++ b/lib/galaxy_utils/sequence/vcf.py Wed Jun 01 11:29:07 2011 -0400
@@ -2,6 +2,8 @@
#See: http://1000genomes.org/wiki/doku.php?id=1000_genomes:analysis:vcf3.3
#See: http://1000genomes.org/wiki/doku.php?id=1000_genomes:analysis:variant_call_…
+NOT_A_NUMBER = float( 'NaN ')
+
class VariantCall( object ):
version = None
header_startswith = None
@@ -40,7 +42,10 @@
self.chrom, self.pos, self.id, self.ref, self.alt, self.qual, self.filter, self.info = self.fields[ :self.required_header_length ]
self.pos = int( self.pos )
self.alt = self.alt.split( ',' )
- self.qual = float( self.qual )
+ try:
+ self.qual = float( self.qual )
+ except:
+ self.qual = NOT_A_NUMBER #Missing data can be denoted as a '.'
if len( self.fields ) > self.required_header_length:
self.format = self.fields[ self.required_header_length ].split( ':' )
for sample_value in self.fields[ self.required_header_length + 1: ]:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

31 May '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/10c1c31c03bc/
changeset: 10c1c31c03bc
branches:
user: greg
date: 2011-05-31 18:03:52
summary: Fix for importing library datasets into a new named history. Library datasets will no longer be imported into both the current history and the new named history ( only the latter ) in this scenario.
affected #: 1 file (53 bytes)
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0