galaxy-commits
Threads by month
- ----- 2026 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- 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
25 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0a37731994c9/
Changeset: 0a37731994c9
User: saketkc
Date: 2013-06-19 08:51:46
Summary: Adding a small check to skip the assertion of tagNumber being
an integer for VCF4.1 files.
I am not sure if there are better ways or beter checks that can be implemen=
ted to
do this. So, this should require discussions.
The description of ##INFO and ##FORMAT tag as given on
[http://www.1000genomes.org/wiki/Analysis/Variant%20Call%20Format/vcf-varia=
nt-call-format-version-41]
is :
##INFO=3D<ID=3DID,Number=3Dnumber,Type=3Dtype,Description=3D=E2=80=9Ddescri=
ption=E2=80=9D>
Possible Types for INFO fields are: Integer, Float, Flag, Character, and St=
ring.
The Number entry is an Integer that describes the number of values that can=
be included with the INFO field.
For example, if the INFO field contains a single number, then this value sh=
ould be 1;
if the INFO field describes a pair of numbers, then this value should be 2 =
and so on.
If the field has one value per alternate allele then this value should be '=
A';
if the field has one value for each possible genotype (more relevant to the=
FORMAT tags) then this value should be 'G'.
If the number of possible values varies, is unknown, or is unbounded, then =
this value should be '.'.
The 'Flag' type indicates that the INFO field does not contain a Value entr=
y, and hence the Number should
be 0 in this case. The Description value must be surrounded by double-quote=
s.
Double-quote character can be escaped with backslash (\") and backslash as =
\\.
Affected #: 1 file
diff -r 81a2bb351c1a0f545a1f69b5514a29d96eb4575a -r 0a37731994c91fd59d2d31f=
79156abb58cc76d75 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/ebdaa310677b/
Changeset: ebdaa310677b
User: saketkc
Date: 2013-06-19 08:52:22
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 170dd4c157b8b5e010804ba4a1ef3b5da08fa49d -r ebdaa310677b57337f5fcc0=
aa2ac475379bf271c tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/493bee44220a/
Changeset: 493bee44220a
User: saketkc
Date: 2013-06-20 05:58:14
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 36d9e5bcd2cbcd5b34b2ae0e7839a71a55350011 -r 493bee44220a54f4d0595bf=
3fd49efdf8a8795bd tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/a52434fb61a8/
Changeset: a52434fb61a8
User: saketkc
Date: 2013-06-20 18:32:29
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 7362302b2c638d377931fa710d40ba2f86f25dba -r a52434fb61a8968735ed1b5=
03b6a5b2b253963ea tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/b1bb5b64dd8e/
Changeset: b1bb5b64dd8e
User: saketkc
Date: 2013-06-20 18:58:11
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 13b5283f964cfa7364b653f2c578b4d7cc27c6e5 -r b1bb5b64dd8eb871451b6bd=
489cc26a6c08dbb7e tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/caa8fd7a0dcf/
Changeset: caa8fd7a0dcf
User: saketkc
Date: 2013-06-20 19:02:55
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 89e7db1cd8098fd6191ab3b4af92e4af32e4c651 -r caa8fd7a0dcf279fec70c3d=
1581296610fc6f636 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/adb63b769897/
Changeset: adb63b769897
User: saketkc
Date: 2013-06-21 07:01:54
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r cf58e35b3a973311ab291e90b501c6f4bc31b6d3 -r adb63b769897f2d2f34b935=
d1a9597df6d1a9cdf tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/b092c9d9a17b/
Changeset: b092c9d9a17b
User: saketkc
Date: 2013-06-21 12:18:18
Summary: Automated merge with ssh://bitbucket.org/saketkc/galaxy-central
Affected #: 1 file
diff -r adb63b769897f2d2f34b935d1a9597df6d1a9cdf -r b092c9d9a17b448e5cb7249=
828dbcd90ab27f1f1 lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -246,8 +246,8 @@
return module_factory.from_dict(trans, from_json_string(st=
ep.config), secure=3DFalse)
module =3D Class( trans, tool_id )
module.state =3D galaxy.tools.DefaultToolState()
- if step.tool_version and (step.tool_version !=3D tool.version=
):
- module.version_changes.append("%s: using version '%s' inst=
ead of version '%s' indicated in this workflow." % (tool_id, tool.version, =
step.tool_version))
+ if step.tool_version and (step.tool_version !=3D module.tool.v=
ersion):
+ module.version_changes.append("%s: using version '%s' inst=
ead of version '%s' indicated in this workflow." % (tool_id, module.tool.ve=
rsion, step.tool_version))
module.state.inputs =3D module.tool.params_from_strings( step.=
tool_inputs, trans.app, ignore_errors=3DTrue )
module.errors =3D step.tool_errors
# module.post_job_actions =3D step.post_job_actions
https://bitbucket.org/galaxy/galaxy-central/commits/46f4beebb766/
Changeset: 46f4beebb766
User: saketkc
Date: 2013-06-22 12:02:56
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 4f7b7e4ca213498824d5fba7526676ddf976b823 -r 46f4beebb766fd75edb59bc=
3598342ef95775af9 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/1ff57c7a9deb/
Changeset: 1ff57c7a9deb
User: saketkc
Date: 2013-06-26 21:44:43
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 62 files
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -267,25 +267,25 @@
# bam does not use '#' to indicate comments/headers - we need to strip=
out those headers from the std. providers
#TODO:?? seems like there should be an easier way to do/inherit this -=
metadata.comment_char?
#TODO: incorporate samtools options to control output: regions first, =
then flags, etc.
- @dataproviders.decorators.dataprovider_factory( 'line' )
+ @dataproviders.decorators.dataprovider_factory( 'line', dataproviders.=
line.FilteredLineDataProvider.settings )
def line_dataprovider( self, dataset, **settings ):
samtools_source =3D dataproviders.dataset.SamtoolsDataProvider( da=
taset )
settings[ 'comment_char' ] =3D '@'
return dataproviders.line.FilteredLineDataProvider( samtools_sourc=
e, **settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'regex-line' )
+ @dataproviders.decorators.dataprovider_factory( 'regex-line', dataprov=
iders.line.RegexLineDataProvider.settings )
def regex_line_dataprovider( self, dataset, **settings ):
samtools_source =3D dataproviders.dataset.SamtoolsDataProvider( da=
taset )
settings[ 'comment_char' ] =3D '@'
return dataproviders.line.RegexLineDataProvider( samtools_source, =
**settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'column' )
+ @dataproviders.decorators.dataprovider_factory( 'column', dataprovider=
s.column.ColumnarDataProvider.settings )
def column_dataprovider( self, dataset, **settings ):
samtools_source =3D dataproviders.dataset.SamtoolsDataProvider( da=
taset )
settings[ 'comment_char' ] =3D '@'
return dataproviders.column.ColumnarDataProvider( samtools_source,=
**settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'map' )
+ @dataproviders.decorators.dataprovider_factory( 'map', dataproviders.c=
olumn.MapDataProvider.settings )
def map_dataprovider( self, dataset, **settings ):
samtools_source =3D dataproviders.dataset.SamtoolsDataProvider( da=
taset )
settings[ 'comment_char' ] =3D '@'
@@ -293,30 +293,30 @@
=20
# these can't be used directly - may need BamColumn, BamMap (Bam metad=
ata -> column/map)
# OR - see genomic_region_dataprovider
- #(a)dataproviders.decorators.dataprovider_factory( 'dataset-column' )
+ #(a)dataproviders.decorators.dataprovider_factory( 'dataset-column', dat=
aproviders.column.ColumnarDataProvider.settings )
#def dataset_column_dataprovider( self, dataset, **settings ):
# settings[ 'comment_char' ] =3D '@'
# return super( Sam, self ).dataset_column_dataprovider( dataset, *=
*settings )
=20
- #(a)dataproviders.decorators.dataprovider_factory( 'dataset-map' )
+ #(a)dataproviders.decorators.dataprovider_factory( 'dataset-map', datapr=
oviders.column.MapDataProvider.settings )
#def dataset_map_dataprovider( self, dataset, **settings ):
# settings[ 'comment_char' ] =3D '@'
# return super( Sam, self ).dataset_map_dataprovider( dataset, **se=
ttings )
=20
- @dataproviders.decorators.dataprovider_factory( 'header' )
+ @dataproviders.decorators.dataprovider_factory( 'header', dataprovider=
s.line.RegexLineDataProvider.settings )
def header_dataprovider( self, dataset, **settings ):
# in this case we can use an option of samtools view to provide ju=
st what we need (w/o regex)
samtools_source =3D dataproviders.dataset.SamtoolsDataProvider( da=
taset, '-H' )
return dataproviders.line.RegexLineDataProvider( samtools_source, =
**settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'id-seq-qual' )
+ @dataproviders.decorators.dataprovider_factory( 'id-seq-qual', datapro=
viders.column.MapDataProvider.settings )
def id_seq_qual_dataprovider( self, dataset, **settings ):
settings[ 'indeces' ] =3D [ 0, 9, 10 ]
settings[ 'column_types' ] =3D [ 'str', 'str', 'str' ]
settings[ 'column_names' ] =3D [ 'id', 'seq', 'qual' ]
return self.map_dataprovider( dataset, **settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'genomic-region' )
+ @dataproviders.decorators.dataprovider_factory( 'genomic-region', data=
providers.column.ColumnarDataProvider.settings )
def genomic_region_dataprovider( self, dataset, **settings ):
# GenomicRegionDataProvider currently requires a dataset as source=
- may not be necc.
#TODO:?? consider (at least) the possible use of a kwarg: metadata=
_source (def. to source.dataset),
@@ -330,7 +330,7 @@
settings[ 'column_types' ] =3D [ 'str', 'int', 'int' ]
return self.column_dataprovider( dataset, **settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'genomic-region-map' )
+ @dataproviders.decorators.dataprovider_factory( 'genomic-region-map', =
dataproviders.column.MapDataProvider.settings )
def genomic_region_map_dataprovider( self, dataset, **settings ):
settings[ 'indeces' ] =3D [ 2, 3, 3 ]
settings[ 'column_types' ] =3D [ 'str', 'int', 'int' ]
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/datatypes/data.py
--- a/lib/galaxy/datatypes/data.py
+++ b/lib/galaxy/datatypes/data.py
@@ -593,7 +593,6 @@
Base dataprovider factory for all datatypes that returns the prope=
r provider
for the given `data_format` or raises a `NoProviderAvailable`.
"""
- #TODO:?? is this handling super class providers?
if self.has_dataprovider( data_format ):
return self.dataproviders[ data_format ]( self, dataset, **set=
tings )
raise dataproviders.exceptions.NoProviderAvailable( self, data_for=
mat )
@@ -603,12 +602,12 @@
dataset_source =3D dataproviders.dataset.DatasetDataProvider( data=
set )
return dataproviders.base.DataProvider( dataset_source, **settings=
)
=20
- @dataproviders.decorators.dataprovider_factory( 'chunk' )
+ @dataproviders.decorators.dataprovider_factory( 'chunk', dataproviders=
.chunk.ChunkDataProvider.settings )
def chunk_dataprovider( self, dataset, **settings ):
dataset_source =3D dataproviders.dataset.DatasetDataProvider( data=
set )
return dataproviders.chunk.ChunkDataProvider( dataset_source, **se=
ttings )
=20
- @dataproviders.decorators.dataprovider_factory( 'chunk64' )
+ @dataproviders.decorators.dataprovider_factory( 'chunk64', dataprovide=
rs.chunk.Base64ChunkDataProvider.settings )
def chunk64_dataprovider( self, dataset, **settings ):
dataset_source =3D dataproviders.dataset.DatasetDataProvider( data=
set )
return dataproviders.chunk.Base64ChunkDataProvider( dataset_source=
, **settings )
@@ -785,7 +784,7 @@
split =3D classmethod(split)
=20
# ------------- Dataproviders
- @dataproviders.decorators.dataprovider_factory( 'line' )
+ @dataproviders.decorators.dataprovider_factory( 'line', dataproviders.=
line.FilteredLineDataProvider.settings )
def line_dataprovider( self, dataset, **settings ):
"""
Returns an iterator over the dataset's lines (that have been `stri=
p`ed)
@@ -794,7 +793,7 @@
dataset_source =3D dataproviders.dataset.DatasetDataProvider( data=
set )
return dataproviders.line.FilteredLineDataProvider( dataset_source=
, **settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'regex-line' )
+ @dataproviders.decorators.dataprovider_factory( 'regex-line', dataprov=
iders.line.RegexLineDataProvider.settings )
def regex_line_dataprovider( self, dataset, **settings ):
"""
Returns an iterator over the dataset's lines
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/datatypes/dataproviders/base.py
--- a/lib/galaxy/datatypes/dataproviders/base.py
+++ b/lib/galaxy/datatypes/dataproviders/base.py
@@ -22,8 +22,13 @@
=20
icorporate existing visualization/dataproviders
some of the sources (esp. in datasets) don't need to be re-created
+YAGNI: InterleavingMultiSourceDataProvider, CombiningMultiSourceDataProvid=
er
=20
-YAGNI: InterleavingMultiSourceDataProvider, CombiningMultiSourceDataProvid=
er
+datasets API entry point:
+ kwargs should be parsed from strings 2 layers up (in the DatasetsAPI) =
- that's the 'proper' place for that.
+ but how would it know how/what to parse if it doesn't have access to t=
he classes used in the provider?
+ Building a giant list by sweeping all possible dprov classes doesn=
't make sense
+ For now - I'm burying them in the class __init__s - but I don't like t=
hat
"""
=20
import logging
@@ -31,6 +36,31 @@
=20
=20
# ------------------------------------------------------------------------=
----- base classes
+class HasSettings( type ):
+ """
+ Metaclass for data providers that allows defining and inheriting
+ a dictionary named 'settings'.
+
+ Useful for allowing class level access to expected variable types
+ passed to class `__init__` functions so they can be parsed from a quer=
y string.
+ """
+ # yeah - this is all too acrobatic
+ def __new__( cls, name, base_classes, attributes ):
+ settings =3D {}
+ # get settings defined in base classes
+ for base_class in base_classes:
+ base_settings =3D getattr( base_class, 'settings', None )
+ if base_settings:
+ settings.update( base_settings )
+ # get settings defined in this class
+ new_settings =3D attributes.pop( 'settings', None )
+ if new_settings:
+ settings.update( new_settings )
+ attributes[ 'settings' ] =3D settings
+ return type.__new__( cls, name, base_classes, attributes )
+
+
+# ------------------------------------------------------------------------=
----- base classes
class DataProvider( object ):
"""
Base class for all data providers. Data providers:
@@ -39,6 +69,12 @@
(c) do not allow write methods
(but otherwise implement the other file object interface metho=
ds)
"""
+ # a definition of expected types for keyword arguments sent to __init__
+ # useful for controlling how query string dictionaries can be parsed=
into correct types for __init__
+ # empty in this base class
+ __metaclass__ =3D HasSettings
+ settings =3D {}
+
def __init__( self, source, **kwargs ):
"""
:param source: the source that this iterator will loop over.
@@ -130,13 +166,16 @@
- `num_valid_data_read`: how many data have been returned from `fi=
lter`.
- `num_data_returned`: how many data has this provider yielded.
"""
+ # not useful here - we don't want functions over the query string
+ #settings.update({ 'filter_fn': 'function' })
+
def __init__( self, source, filter_fn=3DNone, **kwargs ):
"""
:param filter_fn: a lambda or function that will be passed a datum=
and
return either the (optionally modified) datum or None.
"""
super( FilteredDataProvider, self ).__init__( source, **kwargs )
- self.filter_fn =3D filter_fn
+ self.filter_fn =3D filter_fn if hasattr( filter_fn, '__call__' ) e=
lse None
# count how many data we got from the source
self.num_data_read =3D 0
# how many valid data have we gotten from the source
@@ -179,6 +218,12 @@
=20
Useful for grabbing sections from a source (e.g. pagination).
"""
+ # define the expected types of these __init__ arguments so they can be=
parsed out from query strings
+ settings =3D {
+ 'limit' : 'int',
+ 'offset': 'int'
+ }
+
#TODO: may want to squash this into DataProvider
def __init__( self, source, offset=3D0, limit=3DNone, **kwargs ):
"""
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/datatypes/dataproviders/chunk.py
--- a/lib/galaxy/datatypes/dataproviders/chunk.py
+++ b/lib/galaxy/datatypes/dataproviders/chunk.py
@@ -26,6 +26,10 @@
"""
MAX_CHUNK_SIZE =3D 2**16
DEFAULT_CHUNK_SIZE =3D MAX_CHUNK_SIZE
+ settings =3D {
+ 'chunk_index' : 'int',
+ 'chunk_size' : 'int'
+ }
=20
#TODO: subclass from LimitedOffsetDataProvider?
# see web/framework/base.iterate_file, util/__init__.file_reader, and =
datatypes.tabular
@@ -38,8 +42,8 @@
(gen. in bytes).
"""
super( ChunkDataProvider, self ).__init__( source, **kwargs )
- self.chunk_size =3D chunk_size
- self.chunk_pos =3D chunk_index * self.chunk_size
+ self.chunk_size =3D int( chunk_size )
+ self.chunk_pos =3D int( chunk_index ) * self.chunk_size
=20
def validate_source( self, source ):
"""
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/datatypes/dataproviders/column.py
--- a/lib/galaxy/datatypes/dataproviders/column.py
+++ b/lib/galaxy/datatypes/dataproviders/column.py
@@ -29,6 +29,14 @@
the same number of columns as the number of indeces asked for (even if=
they
are filled with None).
"""
+ settings =3D {
+ 'indeces' : 'list:int',
+ 'column_count' : 'int',
+ 'column_types' : 'list:str',
+ 'parse_columns' : 'bool',
+ 'deliminator' : 'str'
+ }
+
def __init__( self, source, indeces=3DNone,
column_count=3DNone, column_types=3DNone, parsers=3DNone, pars=
e_columns=3DTrue,
deliminator=3D'\t', **kwargs ):
@@ -91,11 +99,11 @@
# how/whether to parse each column value
self.parsers =3D {}
if parse_columns:
- self.parsers =3D self._get_default_parsers()
+ self.parsers =3D self.get_default_parsers()
# overwrite with user desired parsers
self.parsers.update( parsers or {} )
=20
- def _get_default_parsers( self ):
+ def get_default_parsers( self ):
"""
Return parser dictionary keyed for each columnar type
(as defined in datatypes).
@@ -132,7 +140,7 @@
#'gffstrand': # -, +, ?, or '.' for None, etc.
}
=20
- def _parse_value( self, val, type ):
+ def parse_value( self, val, type ):
"""
Attempt to parse and return the given value based on the given typ=
e.
=20
@@ -153,7 +161,7 @@
return None
return val
=20
- def _get_column_type( self, index ):
+ def get_column_type( self, index ):
"""
Get the column type for the parser from `self.column_types` or `No=
ne`
if the type is unavailable.
@@ -165,18 +173,18 @@
except IndexError, ind_err:
return None
=20
- def _parse_column_at_index( self, columns, parser_index, index ):
+ def parse_column_at_index( self, columns, parser_index, index ):
"""
Get the column type for the parser from `self.column_types` or `No=
ne`
if the type is unavailable.
"""
try:
- return self._parse_value( columns[ index ], self._get_column_t=
ype( parser_index ) )
+ return self.parse_value( columns[ index ], self.get_column_typ=
e( parser_index ) )
# if a selected index is not within columns, return None
except IndexError, index_err:
return None
=20
- def _parse_columns_from_line( self, line ):
+ def parse_columns_from_line( self, line ):
"""
Returns a list of the desired, parsed columns.
:param line: the line to parse
@@ -188,13 +196,13 @@
selected_indeces =3D self.selected_column_indeces or list( xrange(=
len( all_columns ) ) )
parsed_columns =3D []
for parser_index, column_index in enumerate( selected_indeces ):
- parsed_columns.append( self._parse_column_at_index( all_column=
s, parser_index, column_index ) )
+ parsed_columns.append( self.parse_column_at_index( all_columns=
, parser_index, column_index ) )
return parsed_columns
=20
def __iter__( self ):
parent_gen =3D super( ColumnarDataProvider, self ).__iter__()
for line in parent_gen:
- columns =3D self._parse_columns_from_line( line )
+ columns =3D self.parse_columns_from_line( line )
yield columns
=20
#TODO: implement column filters here and not below - flatten hierarchy
@@ -223,6 +231,10 @@
.. note: that the subclass constructors are passed kwargs - so they're
params (limit, offset, etc.) are also applicable here.
"""
+ settings =3D {
+ 'column_names' : 'list:str',
+ }
+
def __init__( self, source, column_names=3DNone, **kwargs ):
"""
:param column_names: an ordered list of strings that will be used =
as the keys
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/datatypes/dataproviders/dataset.py
--- a/lib/galaxy/datatypes/dataproviders/dataset.py
+++ b/lib/galaxy/datatypes/dataproviders/dataset.py
@@ -141,7 +141,7 @@
"""
# metadata columns are 1-based indeces
column =3D getattr( self.dataset.metadata, name )
- return ( column - 1 ) if isinstance( column, int ) else None
+ return ( column - 1 ) if ( isinstance( column, int ) and column > =
0 ) else None
=20
def get_genomic_region_indeces( self, check=3DFalse ):
"""
@@ -271,6 +271,12 @@
"""
# dictionary keys when named_columns=3DTrue
COLUMN_NAMES =3D [ 'chrom', 'start', 'end' ]
+ settings =3D {
+ 'chrom_column' : 'int',
+ 'start_column' : 'int',
+ 'end_column' : 'int',
+ 'named_columns' : 'bool',
+ }
=20
def __init__( self, dataset, chrom_column=3DNone, start_column=3DNone,=
end_column=3DNone, named_columns=3DFalse, **kwargs ):
"""
@@ -333,6 +339,14 @@
'chrom', 'start', 'end' (and 'strand' and 'name' if available).
"""
COLUMN_NAMES =3D [ 'chrom', 'start', 'end', 'strand', 'name' ]
+ settings =3D {
+ 'chrom_column' : 'int',
+ 'start_column' : 'int',
+ 'end_column' : 'int',
+ 'strand_column' : 'int',
+ 'name_column' : 'int',
+ 'named_columns' : 'bool',
+ }
=20
def __init__( self, dataset, chrom_column=3DNone, start_column=3DNone,=
end_column=3DNone,
strand_column=3DNone, name_column=3DNone, named_columns=
=3DFalse, **kwargs ):
@@ -349,25 +363,40 @@
dataset_source =3D DatasetDataProvider( dataset )
=20
# get genomic indeces and add strand and name
+ self.column_names =3D []
+ indeces =3D []
+ #TODO: this is sort of involved and oogly
if chrom_column =3D=3D None:
chrom_column =3D dataset_source.get_metadata_column_index_by_n=
ame( 'chromCol' )
+ if chrom_column !=3D None:
+ self.column_names.append( 'chrom' )
+ indeces.append( chrom_column )
if start_column =3D=3D None:
start_column =3D dataset_source.get_metadata_column_index_by_n=
ame( 'startCol' )
+ if start_column !=3D None:
+ self.column_names.append( 'start' )
+ indeces.append( start_column )
if end_column =3D=3D None:
end_column =3D dataset_source.get_metadata_column_index_by_nam=
e( 'endCol' )
+ if end_column !=3D None:
+ self.column_names.append( 'end' )
+ indeces.append( end_column )
if strand_column =3D=3D None:
strand_column =3D dataset_source.get_metadata_column_index_by_=
name( 'strandCol' )
+ if strand_column !=3D None:
+ self.column_names.append( 'strand' )
+ indeces.append( strand_column )
if name_column =3D=3D None:
name_column =3D dataset_source.get_metadata_column_index_by_na=
me( 'nameCol' )
- indeces =3D [ chrom_column, start_column, end_column, strand_colum=
n, name_column ]
+ if name_column !=3D None:
+ self.column_names.append( 'name' )
+ indeces.append( name_column )
+
kwargs.update({ 'indeces' : indeces })
-
if not kwargs.get( 'column_types', None ):
kwargs.update({ 'column_types' : dataset_source.get_metadata_c=
olumn_types( indeces=3Dindeces ) })
=20
self.named_columns =3D named_columns
- if self.named_columns:
- self.column_names =3D self.COLUMN_NAMES
=20
super( IntervalDataProvider, self ).__init__( dataset_source, **kw=
args )
=20
@@ -390,6 +419,10 @@
sequence: <joined lines of nucleotide/amino data>
}
"""
+ settings =3D {
+ 'ids' : 'list:str',
+ }
+
def __init__( self, source, ids=3DNone, **kwargs ):
"""
:param ids: optionally return only ids (and sequences) that are in=
this list.
@@ -419,6 +452,10 @@
sequence: <joined lines of nucleotide/amino data>
}
"""
+ settings =3D {
+ 'ids' : 'list:str',
+ }
+
def __init__( self, source, ids=3DNone, **kwargs ):
"""
:param ids: optionally return only ids (and sequences) that are in=
this list.
@@ -445,6 +482,10 @@
Class that returns chrom, pos, data from a wiggle source.
"""
COLUMN_NAMES =3D [ 'chrom', 'pos', 'value' ]
+ settings =3D {
+ 'named_columns' : 'bool',
+ 'column_names' : 'list:str',
+ }
=20
def __init__( self, source, named_columns=3DFalse, column_names=3DNone=
, **kwargs ):
"""
@@ -483,6 +524,10 @@
Class that returns chrom, pos, data from a wiggle source.
"""
COLUMN_NAMES =3D [ 'chrom', 'pos', 'value' ]
+ settings =3D {
+ 'named_columns' : 'bool',
+ 'column_names' : 'list:str',
+ }
=20
def __init__( self, source, chrom, start, end, named_columns=3DFalse, =
column_names=3DNone, **kwargs ):
"""
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/datatypes/dataproviders/decorators.py
--- a/lib/galaxy/datatypes/dataproviders/decorators.py
+++ b/lib/galaxy/datatypes/dataproviders/decorators.py
@@ -87,17 +87,40 @@
# log.debug( '\t\t ', fn.__doc__ )
return cls
=20
-def dataprovider_factory( name ):
+def dataprovider_factory( name, settings=3DNone ):
"""
- Wraps a class method and marks it as a dataprovider factory.
+ Wraps a class method and marks it as a dataprovider factory and create=
s a
+ function to parse query strings to __init__ arguments as the
+ `parse_query_string_settings` attribute of the factory function.
+
+ An example use of the `parse_query_string_settings`:
+ ..example::
+ kwargs =3D dataset.datatype.dataproviders[ provider ].parse_query_stri=
ng_settings( query_kwargs )
+ return list( dataset.datatype.dataprovider( dataset, provider, **kwarg=
s ) )
=20
:param name: what name/key to register the factory under in `cls.datap=
roviders`
- :param type: any hashable var
+ :type name: any hashable var
+ :param settings: dictionary containing key/type pairs for parsing quer=
y strings
+ to __init__ arguments
+ :type settings: dictionary
"""
+ #TODO:?? use *args for settings allowing mulitple dictionaries
+ # make a function available through the name->provider dispatch to par=
se query strings
+ # callable like:
+ # settings_dict =3D dataproviders[ provider_name ].parse_query_string_=
settings( query_kwargs )
+ #TODO: ugh - overly complicated but the best I could think of
+ def parse_query_string_settings( query_kwargs ):
+ return _parse_query_string_settings( query_kwargs, settings )
+
#log.debug( 'dataprovider:', name )
def named_dataprovider_factory( func ):
#log.debug( 'named_dataprovider_factory:', name, '->', func.__name=
__ )
setattr( func, _DATAPROVIDER_METHOD_NAME_KEY, name )
+
+ setattr( func, 'parse_query_string_settings', parse_query_string_s=
ettings )
+ setattr( func, 'settings', settings )
+ #TODO: I want a way to inherit settings from the previous provider=
( this_name ) instead of defining over and over
+
#log.debug( '\t setting:', getattr( func, _DATAPROVIDER_METHOD_NAM=
E_KEY ) )
@wraps( func )
def wrapped_dataprovider_factory( self, *args, **kwargs ):
@@ -105,3 +128,38 @@
return func( self, *args, **kwargs )
return wrapped_dataprovider_factory
return named_dataprovider_factory
+
+def _parse_query_string_settings( query_kwargs, settings=3DNone ):
+ """
+ Parse the values in `query_kwargs` from strings to the proper types
+ listed in the same key in `settings`.
+ """
+ def list_from_query_string( s ):
+ # assume csv
+ return s.split( ',' )
+
+ parsers =3D {
+ 'int' : int,
+ 'float' : float,
+ 'bool' : bool,
+ 'list:str' : lambda s: list_from_query_string( s ),
+ 'list:int' : lambda s: [ int( i ) for i in list_from_query_string=
( s ) ],
+ }
+ settings =3D settings or {}
+ # yay! yet another set of query string parsers! <-- sarcasm
+ # work through the keys in settings finding matching keys in query_kwa=
rgs
+ # if found in both, get the expected/needed type from settings and s=
tore the new parsed value
+ # if we can't parse it (no parser, bad value), delete the key from q=
uery_kwargs so the provider will use the defaults
+ for key in settings:
+ if key in query_kwargs:
+ #TODO: this would be the place to sanitize any strings
+ query_value =3D query_kwargs[ key ]
+ needed_type =3D settings[ key ]
+ try:
+ query_kwargs[ key ] =3D parsers[ needed_type ]( query_valu=
e )
+ except ( KeyError, ValueError ):
+ del query_kwargs[ key ]
+
+ #TODO:?? do we want to remove query_kwarg entries NOT in settings?
+ return query_kwargs
+
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/datatypes/dataproviders/line.py
--- a/lib/galaxy/datatypes/dataproviders/line.py
+++ b/lib/galaxy/datatypes/dataproviders/line.py
@@ -27,6 +27,12 @@
to return.
"""
DEFAULT_COMMENT_CHAR =3D '#'
+ settings =3D {
+ 'string_lines' : 'bool',
+ 'provide_blank' : 'bool',
+ 'comment_char' : 'str',
+ }
+
def __init__( self, source, strip_lines=3DTrue, provide_blank=3DFalse,=
comment_char=3DDEFAULT_COMMENT_CHAR, **kwargs ):
"""
:param strip_lines: remove whitespace from the beginning an ending
@@ -78,6 +84,11 @@
.. note:: the regex matches are effectively OR'd (if **any** regex mat=
ches
the line it is considered valid and will be provided).
"""
+ settings =3D {
+ 'regex_list' : 'list:str',
+ 'invert' : 'bool',
+ }
+
def __init__( self, source, regex_list=3DNone, invert=3DFalse, **kwarg=
s ):
"""
:param regex_list: list of strings or regular expression strings t=
hat will
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/datatypes/interval.py
--- a/lib/galaxy/datatypes/interval.py
+++ b/lib/galaxy/datatypes/interval.py
@@ -334,20 +334,24 @@
return None
=20
# ------------- Dataproviders
- @dataproviders.decorators.dataprovider_factory( 'genomic-region' )
+ @dataproviders.decorators.dataprovider_factory( 'genomic-region',
+ dataproviders.dataset.=
GenomicRegionDataProvider.settings )
def genomic_region_dataprovider( self, dataset, **settings ):
return dataproviders.dataset.GenomicRegionDataProvider( dataset, *=
*settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'genomic-region-map' )
+ @dataproviders.decorators.dataprovider_factory( 'genomic-region-map',
+ dataproviders.dataset.=
GenomicRegionDataProvider.settings )
def genomic_region_map_dataprovider( self, dataset, **settings ):
settings[ 'named_columns' ] =3D True
return self.genomic_region_dataprovider( dataset, **settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'interval' )
+ @dataproviders.decorators.dataprovider_factory( 'interval',
+ dataproviders.dataset.=
IntervalDataProvider.settings )
def interval_dataprovider( self, dataset, **settings ):
return dataproviders.dataset.IntervalDataProvider( dataset, **sett=
ings )
=20
- @dataproviders.decorators.dataprovider_factory( 'interval-map' )
+ @dataproviders.decorators.dataprovider_factory( 'interval-map',
+ dataproviders.dataset.=
IntervalDataProvider.settings )
def interval_map_dataprovider( self, dataset, **settings ):
settings[ 'named_columns' ] =3D True
return self.interval_dataprovider( dataset, **settings )
@@ -809,20 +813,24 @@
=20
# ------------- Dataproviders
# redefine bc super is Tabular
- @dataproviders.decorators.dataprovider_factory( 'genomic-region' )
+ @dataproviders.decorators.dataprovider_factory( 'genomic-region',
+ dataproviders.dataset.=
GenomicRegionDataProvider.settings )
def genomic_region_dataprovider( self, dataset, **settings ):
return dataproviders.dataset.GenomicRegionDataProvider( dataset, 0=
, 3, 4, **settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'genomic-region-map' )
+ @dataproviders.decorators.dataprovider_factory( 'genomic-region-map',
+ dataproviders.dataset.=
GenomicRegionDataProvider.settings )
def genomic_region_map_dataprovider( self, dataset, **settings ):
settings[ 'named_columns' ] =3D True
return self.genomic_region_dataprovider( dataset, **settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'interval' )
+ @dataproviders.decorators.dataprovider_factory( 'interval',
+ dataproviders.dataset.=
IntervalDataProvider.settings )
def interval_dataprovider( self, dataset, **settings ):
return dataproviders.dataset.IntervalDataProvider( dataset, 0, 3, =
4, 6, 2, **settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'interval-map' )
+ @dataproviders.decorators.dataprovider_factory( 'interval-map',
+ dataproviders.dataset.=
IntervalDataProvider.settings )
def interval_map_dataprovider( self, dataset, **settings ):
settings[ 'named_columns' ] =3D True
return self.interval_dataprovider( dataset, **settings )
@@ -1193,12 +1201,12 @@
return resolution
=20
# ------------- Dataproviders
- @dataproviders.decorators.dataprovider_factory( 'wiggle' )
+ @dataproviders.decorators.dataprovider_factory( 'wiggle', dataprovider=
s.dataset.WiggleDataProvider.settings )
def wiggle_dataprovider( self, dataset, **settings ):
dataset_source =3D dataproviders.dataset.DatasetDataProvider( data=
set )
return dataproviders.dataset.WiggleDataProvider( dataset_source, *=
*settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'wiggle-map' )
+ @dataproviders.decorators.dataprovider_factory( 'wiggle-map', dataprov=
iders.dataset.WiggleDataProvider.settings )
def wiggle_map_dataprovider( self, dataset, **settings ):
dataset_source =3D dataproviders.dataset.DatasetDataProvider( data=
set )
settings[ 'named_columns' ] =3D True
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/datatypes/sequence.py
--- a/lib/galaxy/datatypes/sequence.py
+++ b/lib/galaxy/datatypes/sequence.py
@@ -15,8 +15,6 @@
from galaxy import util
from sniff import *
=20
-from galaxy.datatypes import dataproviders
-
import pkg_resources
pkg_resources.require("simplejson")
import simplejson
@@ -399,15 +397,6 @@
f.close()
_count_split =3D classmethod(_count_split)
=20
- def provider( self, dataset, data_format, **settings ):
- from galaxy.dataproviders import dataset as dataset_providers
-
- if data_format =3D=3D 'id_seq':
- source =3D dataset_providers.DatasetDataProvider( dataset )
- return dataset_providers.FastaDataProvider( source, **settings=
)
-
- return super( Fasta, self ).provider( dataset, data_format, **sett=
ings )
-
=20
class csFasta( Sequence ):
""" Class representing the SOLID Color-Space sequence ( csfasta ) """
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/datatypes/sniff.py
--- a/lib/galaxy/datatypes/sniff.py
+++ b/lib/galaxy/datatypes/sniff.py
@@ -6,6 +6,7 @@
from galaxy import util
from galaxy.datatypes.checkers import *
from encodings import search_function as encodings_search_function
+from binary import Binary
=20
log =3D logging.getLogger(__name__)
=20
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/datatypes/tabular.py
--- a/lib/galaxy/datatypes/tabular.py
+++ b/lib/galaxy/datatypes/tabular.py
@@ -345,26 +345,25 @@
return vizs
=20
# ------------- Dataproviders
- @dataproviders.decorators.dataprovider_factory( 'column' )
+ @dataproviders.decorators.dataprovider_factory( 'column', dataprovider=
s.column.ColumnarDataProvider.settings )
def column_dataprovider( self, dataset, **settings ):
"""Uses column settings that are passed in"""
- print 'Tabular.comment_char:', settings.get( 'comment_char', None )
-
dataset_source =3D dataproviders.dataset.DatasetDataProvider( data=
set )
return dataproviders.column.ColumnarDataProvider( dataset_source, =
**settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'dataset-column' )
+ @dataproviders.decorators.dataprovider_factory( 'dataset-column',
+ dataproviders.column.C=
olumnarDataProvider.settings )
def dataset_column_dataprovider( self, dataset, **settings ):
"""Attempts to get column settings from dataset.metadata"""
return dataproviders.dataset.DatasetColumnarDataProvider( dataset,=
**settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'map' )
+ @dataproviders.decorators.dataprovider_factory( 'map', dataproviders.c=
olumn.MapDataProvider.settings )
def map_dataprovider( self, dataset, **settings ):
"""Uses column settings that are passed in"""
dataset_source =3D dataproviders.dataset.DatasetDataProvider( data=
set )
return dataproviders.column.MapDataProvider( dataset_source, **set=
tings )
=20
- @dataproviders.decorators.dataprovider_factory( 'dataset-map' )
+ @dataproviders.decorators.dataprovider_factory( 'dataset-map', datapro=
viders.column.MapDataProvider.settings )
def dataset_map_dataprovider( self, dataset, **settings ):
"""Attempts to get column settings from dataset.metadata"""
return dataproviders.dataset.DatasetMapDataProvider( dataset, **se=
ttings )
@@ -502,55 +501,58 @@
# ------------- Dataproviders
# sam does not use '#' to indicate comments/headers - we need to strip=
out those headers from the std. providers
#TODO:?? seems like there should be an easier way to do this - metadat=
a.comment_char?
- @dataproviders.decorators.dataprovider_factory( 'line' )
+ @dataproviders.decorators.dataprovider_factory( 'line', dataproviders.=
line.FilteredLineDataProvider.settings )
def line_dataprovider( self, dataset, **settings ):
settings[ 'comment_char' ] =3D '@'
return super( Sam, self ).line_dataprovider( dataset, **settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'regex-line' )
+ @dataproviders.decorators.dataprovider_factory( 'regex-line', dataprov=
iders.line.RegexLineDataProvider.settings )
def regex_line_dataprovider( self, dataset, **settings ):
settings[ 'comment_char' ] =3D '@'
return super( Sam, self ).regex_line_dataprovider( dataset, **sett=
ings )
=20
- @dataproviders.decorators.dataprovider_factory( 'column' )
+ @dataproviders.decorators.dataprovider_factory( 'column', dataprovider=
s.column.ColumnarDataProvider.settings )
def column_dataprovider( self, dataset, **settings ):
settings[ 'comment_char' ] =3D '@'
return super( Sam, self ).column_dataprovider( dataset, **settings=
)
=20
- @dataproviders.decorators.dataprovider_factory( 'dataset-column' )
+ @dataproviders.decorators.dataprovider_factory( 'dataset-column',
+ dataproviders.column.C=
olumnarDataProvider.settings )
def dataset_column_dataprovider( self, dataset, **settings ):
settings[ 'comment_char' ] =3D '@'
return super( Sam, self ).dataset_column_dataprovider( dataset, **=
settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'map' )
+ @dataproviders.decorators.dataprovider_factory( 'map', dataproviders.c=
olumn.MapDataProvider.settings )
def map_dataprovider( self, dataset, **settings ):
settings[ 'comment_char' ] =3D '@'
return super( Sam, self ).map_dataprovider( dataset, **settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'dataset-map' )
+ @dataproviders.decorators.dataprovider_factory( 'dataset-map', datapro=
viders.column.MapDataProvider.settings )
def dataset_map_dataprovider( self, dataset, **settings ):
settings[ 'comment_char' ] =3D '@'
return super( Sam, self ).dataset_map_dataprovider( dataset, **set=
tings )
=20
- @dataproviders.decorators.dataprovider_factory( 'header' )
+ @dataproviders.decorators.dataprovider_factory( 'header', dataprovider=
s.line.RegexLineDataProvider.settings )
def header_dataprovider( self, dataset, **settings ):
dataset_source =3D dataproviders.dataset.DatasetDataProvider( data=
set )
headers_source =3D dataproviders.line.RegexLineDataProvider( datas=
et_source, regex_list=3D[ '^@' ] )
return dataproviders.line.RegexLineDataProvider( headers_source, *=
*settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'id-seq-qual' )
+ @dataproviders.decorators.dataprovider_factory( 'id-seq-qual', map_dat=
aprovider.settings )
def id_seq_qual_dataprovider( self, dataset, **settings ):
# provided as an example of a specified column map (w/o metadata)
settings[ 'indeces' ] =3D [ 0, 9, 10 ]
settings[ 'column_names' ] =3D [ 'id', 'seq', 'qual' ]
return self.map_dataprovider( dataset, **settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'genomic-region' )
+ @dataproviders.decorators.dataprovider_factory( 'genomic-region',
+ dataproviders.dataset.=
GenomicRegionDataProvider.settings )
def genomic_region_dataprovider( self, dataset, **settings ):
settings[ 'comment_char' ] =3D '@'
return dataproviders.dataset.GenomicRegionDataProvider( dataset, 2=
, 3, 3, **settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'genomic-region-map' )
+ @dataproviders.decorators.dataprovider_factory( 'genomic-region-map',
+ dataproviders.dataset.=
GenomicRegionDataProvider.settings )
def genomic_region_map_dataprovider( self, dataset, **settings ):
settings[ 'comment_char' ] =3D '@'
return dataproviders.dataset.GenomicRegionDataProvider( dataset, 2=
, 3, 3, True, **settings )
@@ -621,11 +623,13 @@
return False
=20
# ------------- Dataproviders
- @dataproviders.decorators.dataprovider_factory( 'genomic-region' )
+ @dataproviders.decorators.dataprovider_factory( 'genomic-region',
+ dataproviders.dataset.=
GenomicRegionDataProvider.settings )
def genomic_region_dataprovider( self, dataset, **settings ):
return dataproviders.dataset.GenomicRegionDataProvider( dataset, *=
*settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'genomic-region-map' )
+ @dataproviders.decorators.dataprovider_factory( 'genomic-region-map',
+ dataproviders.dataset.=
GenomicRegionDataProvider.settings )
def genomic_region_map_dataprovider( self, dataset, **settings ):
settings[ 'named_columns' ] =3D True
return self.genomic_region_dataprovider( dataset, **settings )
@@ -668,11 +672,13 @@
dataset.metadata.sample_names =3D line.split()[ 9: ]
=20
# ------------- Dataproviders
- @dataproviders.decorators.dataprovider_factory( 'genomic-region' )
+ @dataproviders.decorators.dataprovider_factory( 'genomic-region',
+ dataproviders.dataset.=
GenomicRegionDataProvider.settings )
def genomic_region_dataprovider( self, dataset, **settings ):
return dataproviders.dataset.GenomicRegionDataProvider( dataset, 0=
, 1, 1, **settings )
=20
- @dataproviders.decorators.dataprovider_factory( 'genomic-region-map' )
+ @dataproviders.decorators.dataprovider_factory( 'genomic-region-map',
+ dataproviders.dataset.=
GenomicRegionDataProvider.settings )
def genomic_region_map_dataprovider( self, dataset, **settings ):
settings[ 'named_columns' ] =3D True
return self.genomic_region_dataprovider( dataset, **settings )
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/visualization/data_providers/registry.py
--- a/lib/galaxy/visualization/data_providers/registry.py
+++ b/lib/galaxy/visualization/data_providers/registry.py
@@ -32,7 +32,7 @@
"bigwig": genome.BigWigDataProvider,
"bigbed": genome.BigBedDataProvider,
=20
- "column": ColumnDataProvider
+ "column_with_stats": ColumnDataProvider
}
=20
def get_data_provider( self, trans, name=3DNone, source=3D'data', raw=
=3DFalse, original_dataset=3DNone ):
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/visualization/registry.py
--- a/lib/galaxy/visualization/registry.py
+++ b/lib/galaxy/visualization/registry.py
@@ -15,22 +15,27 @@
log =3D logging.getLogger( __name__ )
=20
__TODO__ =3D """
- BUGS:
- anon users clicking a viz link gets 'must be' msg in galaxy_main (=
w/ masthead)
- should not show visualizations (no icon)?
- newick files aren't being sniffed prop? - datatype is txt
+BUGS:
+ anon users clicking a viz link gets 'must be' msg in galaxy_main (w/ m=
asthead)
+ should not show visualizations (no icon)?
+ newick files aren't being sniffed prop? - datatype is txt
=20
- have parsers create objects instead of dicts
- allow data_sources with no model_class but have tests (isAdmin, etc.)
- maybe that's an instance of User model_class?
- some confused vocabulary in docs, var names
- tests:
- anding, grouping, not
- data_sources:
- lists of
- add description element to visualization.
+have parsers create objects instead of dicts
+allow data_sources with no model_class but have tests (isAdmin, etc.)
+ maybe that's an instance of User model_class?
+some confused vocabulary in docs, var names
+tests:
+ anding, grouping, not
+data_sources:
+ lists of
+add description element to visualization.
+
+TESTS to add:
+ has dataprovider
+ user is admin
"""
=20
+# ------------------------------------------------------------------- the =
registry
class VisualizationsRegistry( object ):
"""
Main responsibilities are:
@@ -93,6 +98,45 @@
"""
self.listings =3D VisualizationsConfigParser.parse( self.configura=
tion_filepath )
=20
+ def get_visualization( self, trans, visualization_name, target_object =
):
+ """
+ Return data to build a url to the visualization with the given
+ `visualization_name` if it's applicable to `target_object` or
+ `None` if it's not.
+ """
+ # a little weird to pass trans because this registry is part of th=
e trans.app
+ listing_data =3D self.listings.get( visualization_name, None )
+ if not listing_data:
+ return None
+
+ data_sources =3D listing_data[ 'data_sources' ]
+ for data_source in data_sources:
+ # currently a model class is required
+ model_class =3D data_source[ 'model_class' ]
+ if not isinstance( target_object, model_class ):
+ continue
+
+ # tests are optional - default is the above class test
+ tests =3D data_source[ 'tests' ]
+ if tests and not self.is_object_applicable( trans, target_obje=
ct, tests ):
+ continue
+
+ param_data =3D data_source[ 'to_params' ]
+ url =3D self.get_visualization_url( trans, target_object, visu=
alization_name, param_data )
+ link_text =3D listing_data.get( 'link_text', None )
+ if not link_text:
+ # default to visualization name, titlecase, and replace un=
derscores
+ link_text =3D visualization_name.title().replace( '_', ' '=
)
+ render_location =3D listing_data.get( 'render_location' )
+ # remap some of these vars for direct use in ui.js, PopupMenu =
(e.g. text->html)
+ return {
+ 'href' : url,
+ 'html' : link_text,
+ 'target': render_location
+ }
+
+ return None
+
# -- building links to visualizations from objects --
def get_visualizations( self, trans, target_object ):
"""
@@ -100,36 +144,11 @@
the urls to call in order to render the visualizations.
"""
#TODO:?? a list of objects? YAGNI?
- # a little weird to pass trans because this registry is part of th=
e trans.app
applicable_visualizations =3D []
- for vis_name, listing_data in self.listings.items():
-
- data_sources =3D listing_data[ 'data_sources' ]
- for data_source in data_sources:
- # currently a model class is required
- model_class =3D data_source[ 'model_class' ]
- if not isinstance( target_object, model_class ):
- continue
-
- # tests are optional - default is the above class test
- tests =3D data_source[ 'tests' ]
- if tests and not self.is_object_applicable( trans, target_=
object, tests ):
- continue
-
- param_data =3D data_source[ 'to_params' ]
- url =3D self.get_visualization_url( trans, target_object, =
vis_name, param_data )
- link_text =3D listing_data.get( 'link_text', None )
- if not link_text:
- # default to visualization name, titlecase, and replac=
e underscores
- link_text =3D vis_name.title().replace( '_', ' ' )
- render_location =3D listing_data.get( 'render_location' )
- # remap some of these vars for direct use in ui.js, PopupM=
enu (e.g. text->html)
- applicable_visualizations.append({
- 'href' : url,
- 'html' : link_text,
- 'target': render_location
- })
-
+ for vis_name in self.listings:
+ url_data =3D self.get_visualization( trans, vis_name, target_o=
bject )
+ if url_data:
+ applicable_visualizations.append( url_data )
return applicable_visualizations
=20
def is_object_applicable( self, trans, target_object, data_source_test=
s ):
@@ -151,10 +170,11 @@
# convert datatypes to their actual classes (for use w=
ith isinstance)
test_result =3D trans.app.datatypes_registry.get_datat=
ype_class_by_name( test_result )
if not test_result:
- # warn if can't find class, but continue
+ # warn if can't find class, but continue (with oth=
er tests)
log.warn( 'visualizations_registry cannot find cla=
ss (%s) for applicability test', test_result )
continue
=20
+ #NOTE: tests are OR'd, if any test passes - the visualization =
can be applied
if test_fn( target_object, test_result ):
#log.debug( 'test passed' )
return True
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/webapps/galaxy/api/datasets.py
--- a/lib/galaxy/webapps/galaxy/api/datasets.py
+++ b/lib/galaxy/webapps/galaxy/api/datasets.py
@@ -6,6 +6,7 @@
from galaxy.web.base.controller import BaseAPIController, UsesVisualizatio=
nMixin, UsesHistoryDatasetAssociationMixin
from galaxy.web.base.controller import UsesHistoryMixin
from galaxy.web.framework.helpers import is_true
+from galaxy.datatypes import dataproviders
=20
import logging
log =3D logging.getLogger( __name__ )
@@ -217,10 +218,24 @@
return msg
=20
registry =3D trans.app.data_provider_registry
+
# allow the caller to specifiy which provider is used
- if provider and provider in registry.dataset_type_name_to_data_pro=
vider:
- data_provider =3D registry.dataset_type_name_to_data_provider[=
provider ]( dataset )
- # or have it look up by datatype
+ # pulling from the original providers if possible, then the new =
providers
+ if provider:
+ if provider in registry.dataset_type_name_to_data_provider:
+ data_provider =3D registry.dataset_type_name_to_data_provi=
der[ provider ]( dataset )
+
+ elif dataset.datatype.has_dataprovider( provider ):
+ kwargs =3D dataset.datatype.dataproviders[ provider ].pars=
e_query_string_settings( kwargs )
+ # use dictionary to allow more than the data itself to be =
returned (data totals, other meta, etc.)
+ return {
+ 'data': list( dataset.datatype.dataprovider( dataset, =
provider, **kwargs ) )
+ }
+
+ else:
+ raise dataproviders.exceptions.NoProviderAvailable( datase=
t.datatype, provider )
+
+ # no provider name: look up by datatype
else:
data_provider =3D registry.get_data_provider( trans, raw=3DTru=
e, original_dataset=3Ddataset )
=20
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
--- a/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
+++ b/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
@@ -179,6 +179,11 @@
# Get the information about the Galaxy components (e.g., tool pane=
section, tool config file, etc) that will contain the repository informati=
on.
install_repository_dependencies =3D payload.get( 'install_reposito=
ry_dependencies', False )
install_tool_dependencies =3D payload.get( 'install_tool_dependenc=
ies', False )
+ if install_tool_dependencies:
+ if trans.app.config.tool_dependency_dir is None:
+ no_tool_dependency_dir_message =3D "Tool dependencies can =
be automatically installed only if you set the value of your 'tool_dependen=
cy_dir' "
+ no_tool_dependency_dir_message +=3D "setting in your Galax=
y configuration file (universe_wsgi.ini) and restart your Galaxy server."
+ raise HTTPBadRequest( detail=3Dno_tool_dependency_dir_mess=
age )
new_tool_panel_section =3D payload.get( 'new_tool_panel_section_la=
bel', '' )
shed_tool_conf =3D payload.get( 'shed_tool_conf', None )
if shed_tool_conf:
@@ -211,13 +216,8 @@
tool_path=3Dtool_path,
tool_shed_url=3Dtool_shed_url )
# Create the tool_shed_repository database records and gather addi=
tional information for repository installation.
- created_or_updated_tool_shed_repositories, tool_panel_section_keys=
, repo_info_dicts, filtered_repo_info_dicts, message =3D \
+ created_or_updated_tool_shed_repositories, tool_panel_section_keys=
, repo_info_dicts, filtered_repo_info_dicts =3D \
repository_util.handle_tool_shed_repositories( trans, installa=
tion_dict, using_api=3DTrue )
- if message and len( repo_info_dicts ) =3D=3D 1:
- # We're attempting to install a single repository that has alr=
eady been installed into this Galaxy instance.
- log.error( message, exc_info=3DTrue )
- trans.response.status =3D 500
- return dict( status=3D'error', error=3Dmessage )
if created_or_updated_tool_shed_repositories:
# Build the dictionary of information necessary for installing=
the repositories.
installation_dict =3D dict( created_or_updated_tool_shed_repos=
itories=3Dcreated_or_updated_tool_shed_repositories,
@@ -266,11 +266,7 @@
acti=
on=3D'show',
id=
=3Dtrans.security.encode_id( tool_shed_repository.id ) )
installed_tool_shed_repositories.append( tool_shed_rep=
ository_dict )
- elif message:
- log.error( message, exc_info=3DTrue )
- trans.response.status =3D 500
- return dict( status=3D'error', error=3Dmessage )
- elif not created_or_updated_tool_shed_repositories and not message:
+ else:
# We're attempting to install more than 1 repository, and all =
of them have already been installed.
return dict( status=3D'error', error=3D'All repositories that =
you are attempting to install have been previously installed.' )
# Display the list of installed repositories.
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -155,7 +155,8 @@
def browse_tool_dependency( self, trans, **kwd ):
message =3D kwd.get( 'message', '' )
status =3D kwd.get( 'status', 'done' )
- tool_dependency =3D tool_dependency_util.get_tool_dependency( tran=
s, kwd[ 'id' ] )
+ tool_dependency_ids =3D tool_dependency_util.get_tool_dependency_i=
ds( as_string=3DFalse, **kwd )
+ tool_dependency =3D tool_dependency_util.get_tool_dependency( tran=
s, tool_dependency_ids[ 0 ] )
if tool_dependency.in_error_state:
message =3D "This tool dependency is not installed correctly (=
see the <b>Tool dependency installation error</b> below). "
message +=3D "Choose <b>Uninstall this tool dependency</b> fro=
m the <b>Repository Actions</b> menu, correct problems "
@@ -482,9 +483,7 @@
def install_tool_dependencies( self, trans, **kwd ):
message =3D kwd.get( 'message', '' )
status =3D kwd.get( 'status', 'done' )
- tool_dependency_ids =3D util.listify( kwd.get( 'tool_dependency_id=
s', None ) )
- if not tool_dependency_ids:
- tool_dependency_ids =3D util.listify( kwd.get( 'id', None ) )
+ tool_dependency_ids =3D tool_dependency_util.get_tool_dependency_i=
ds( as_string=3DFalse, **kwd )
tool_dependencies =3D []
for tool_dependency_id in tool_dependency_ids:
tool_dependency =3D tool_dependency_util.get_tool_dependency( =
trans, tool_dependency_id )
@@ -731,11 +730,11 @@
kwd[ 'status' ] =3D 'error'
installed_tool_dependencies_select_field =3D suc.build_tool_depend=
encies_select_field( trans,
=
tool_shed_repository=3Dtool_shed_repository,
- =
name=3D'tool_dependency_ids',
+ =
name=3D'inst_td_ids',
=
uninstalled=3DFalse )
uninstalled_tool_dependencies_select_field =3D suc.build_tool_depe=
ndencies_select_field( trans,
=
tool_shed_repository=3Dtool_shed_repository,
- =
name=3D'tool_dependency_ids',
+ =
name=3D'uninstalled_tool_dependency_ids',
=
uninstalled=3DTrue )
return trans.fill_template( '/admin/tool_shed_repository/manage_re=
pository_tool_dependencies.mako',
repository=3Dtool_shed_repository,
@@ -886,15 +885,8 @@
tool_panel_section=3Dtool_panel_sect=
ion,
tool_path=3Dtool_path,
tool_shed_url=3Dtool_shed_url )
- created_or_updated_tool_shed_repositories, tool_panel_section_=
keys, repo_info_dicts, filtered_repo_info_dicts, message =3D \
+ created_or_updated_tool_shed_repositories, tool_panel_section_=
keys, repo_info_dicts, filtered_repo_info_dicts =3D \
repository_util.handle_tool_shed_repositories( trans, inst=
allation_dict, using_api=3DFalse )
- if message and len( repo_info_dicts ) =3D=3D 1:
- # We're undoubtedly attempting to install a repository tha=
t has been previously installed.
- return trans.response.send_redirect( web.url_for( controll=
er=3D'admin_toolshed',
- action=
=3D'browse_repositories',
- message=
=3Dmessage,
- status=
=3D'error' ) )
-
if created_or_updated_tool_shed_repositories:
installation_dict =3D dict( created_or_updated_tool_shed_r=
epositories=3Dcreated_or_updated_tool_shed_repositories,
filtered_repo_info_dicts=3Dfilte=
red_repo_info_dicts,
@@ -1128,7 +1120,7 @@
reposi=
tory_dependencies=3Drepository_dependencies )
repo_info_dicts.append( repo_info_dict )
# Make sure all tool_shed_repository records exist.
- created_or_updated_tool_shed_repositories, tool_panel_section_keys=
, repo_info_dicts, filtered_repo_info_dicts, message =3D \
+ created_or_updated_tool_shed_repositories, tool_panel_section_keys=
, repo_info_dicts, filtered_repo_info_dicts =3D \
repository_dependency_util.create_repository_dependency_object=
s( trans=3Dtrans,
=
tool_path=3Dtool_path,
=
tool_shed_url=3Dtool_shed_url,
@@ -1175,6 +1167,18 @@
initiate_repository_installation_ids=
=3Dencoded_repository_ids,
reinstalling=3DTrue )
=20
+ @web.expose
+ @web.require_admin
+ def repair_repository( self, trans, **kwd ):
+ """
+ Inspect the repository dependency hierarchy for a specified reposi=
tory and attempt to make sure they are all properly installed as well as
+ each repository's tool dependencies.
+ """
+ message =3D kwd.get( 'message', '' )
+ status =3D kwd.get( 'status', 'done' )
+ repository_id =3D kwd[ 'id' ]
+ tool_shed_repository =3D suc.get_installed_tool_shed_repository( t=
rans, repository_id )
+
@web.json
def repository_installation_status_updates( self, trans, ids=3DNone, s=
tatus_list=3DNone ):
# Avoid caching
@@ -1517,7 +1521,7 @@
def uninstall_tool_dependencies( self, trans, **kwd ):
message =3D kwd.get( 'message', '' )
status =3D kwd.get( 'status', 'done' )
- tool_dependency_ids =3D util.listify( kwd.get( 'tool_dependency_id=
s', None ) )
+ tool_dependency_ids =3D tool_dependency_util.get_tool_dependency_i=
ds( as_string=3DFalse, **kwd )
if not tool_dependency_ids:
tool_dependency_ids =3D util.listify( kwd.get( 'id', None ) )
tool_dependencies =3D []
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/tool_shed/galaxy_install/repository_util.py
--- a/lib/tool_shed/galaxy_install/repository_util.py
+++ b/lib/tool_shed/galaxy_install/repository_util.py
@@ -358,7 +358,7 @@
tool_panel_section =3D installation_dict[ 'tool_panel_section' ]
tool_path =3D installation_dict[ 'tool_path' ]
tool_shed_url =3D installation_dict[ 'tool_shed_url' ]
- created_or_updated_tool_shed_repositories, tool_panel_section_keys, re=
po_info_dicts, filtered_repo_info_dicts, message =3D \
+ created_or_updated_tool_shed_repositories, tool_panel_section_keys, re=
po_info_dicts, filtered_repo_info_dicts =3D \
repository_dependency_util.create_repository_dependency_objects( t=
rans=3Dtrans,
t=
ool_path=3Dtool_path,
t=
ool_shed_url=3Dtool_shed_url,
@@ -368,11 +368,7 @@
n=
o_changes_checked=3Dno_changes_checked,
t=
ool_panel_section=3Dtool_panel_section,
n=
ew_tool_panel_section=3Dnew_tool_panel_section )
- if message and len( repo_info_dicts ) =3D=3D 1 and not using_api:
- installed_tool_shed_repository =3D created_or_updated_tool_shed_re=
positories[ 0 ]
- message +=3D 'Click <a href=3D"%s">here</a> to manage the reposito=
ry. ' % \
- ( web.url_for( controller=3D'admin_toolshed', action=3D'manage=
_repository', id=3Dtrans.security.encode_id( installed_tool_shed_repository=
.id ) ) )
- return created_or_updated_tool_shed_repositories, tool_panel_section_k=
eys, repo_info_dicts, filtered_repo_info_dicts, message
+ return created_or_updated_tool_shed_repositories, tool_panel_section_k=
eys, repo_info_dicts, filtered_repo_info_dicts
=20
def initiate_repository_installation( trans, installation_dict ):
# The following installation_dict entries are all required.
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/tool_shed/galaxy_install/tool_dependencies/common_uti=
l.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/common_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/common_util.py
@@ -216,7 +216,7 @@
return os.path.abspath( file_path )
raise ValueError( 'Could not find path to file %s' % os.path.abspath( =
os.path.join( file_path, file_name ) ) )
=20
-def url_download( install_dir, downloaded_file_name, download_url ):
+def url_download( install_dir, downloaded_file_name, download_url, extract=
=3DTrue ):
file_path =3D os.path.join( install_dir, downloaded_file_name )
src =3D None
dst =3D None
@@ -236,7 +236,22 @@
src.close()
if dst:
dst.close()
- return os.path.abspath( file_path )
+ if extract:
+ if istar( file_path ):
+ # <action type=3D"download_by_url">http://sourceforge.net/proj=
ects/samtools/files/samtools/0.1.18/samtools-0.1.18.tar.bz2</action>
+ extract_tar( file_path, install_dir )
+ dir =3D tar_extraction_directory( install_dir, downloaded_file=
_name )
+ elif isjar( file_path ):
+ dir =3D os.path.curdir
+ elif iszip( file_path ):
+ # <action type=3D"download_by_url">http://downloads.sourceforg=
e.net/project/picard/picard-tools/1.56/picard-tools-1.56.zip</action>
+ zip_archive_extracted =3D extract_zip( file_path, install_dir )
+ dir =3D zip_extraction_directory( install_dir, downloaded_file=
_name )
+ else:
+ dir =3D install_dir
+ else:
+ dir =3D install_dir
+ return dir
=20
def zip_extraction_directory( file_path, file_name ):
"""Try to return the correct extraction directory."""
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/tool_shed/galaxy_install/tool_dependencies/fabric_uti=
l.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -180,19 +180,7 @@
downloaded_filename =3D action_dict[ 'target_filen=
ame' ]
else:
downloaded_filename =3D os.path.split( url )[ -1 ]
- downloaded_file_path =3D common_util.url_download( wor=
k_dir, downloaded_filename, url )
- if common_util.istar( downloaded_file_path ):
- # <action type=3D"download_by_url">http://sourcefo=
rge.net/projects/samtools/files/samtools/0.1.18/samtools-0.1.18.tar.bz2</ac=
tion>
- common_util.extract_tar( downloaded_file_path, wor=
k_dir )
- dir =3D common_util.tar_extraction_directory( work=
_dir, downloaded_filename )
- elif common_util.isjar( downloaded_file_path ):
- dir =3D os.path.curdir
- elif common_util.iszip( downloaded_file_path ):
- # <action type=3D"download_by_url">http://download=
s.sourceforge.net/project/picard/picard-tools/1.56/picard-tools-1.56.zip</a=
ction>
- zip_archive_extracted =3D common_util.extract_zip(=
downloaded_file_path, work_dir )
- dir =3D common_util.zip_extraction_directory( work=
_dir, downloaded_filename )
- else:
- dir =3D os.path.curdir
+ dir =3D common_util.url_download( work_dir, downloaded=
_filename, url, extract=3DTrue )
elif action_type =3D=3D 'shell_command':
# <action type=3D"shell_command">git clone --recursive=
git://github.com/ekg/freebayes.git</action>
# Eliminate the shell_command clone action so remainin=
g actions can be processed correctly.
@@ -206,7 +194,7 @@
# Download a single file to the working directory.
filtered_actions =3D actions[ 1: ]
url =3D action_dict[ 'url' ]
- if action_dict[ 'target_filename' ]:
+ if 'target_filename' in action_dict:
# Sometimes compressed archives extracts their con=
tent to a folder other than the default defined file name. Using this
# attribute will ensure that the file name is set =
appropriately and can be located after download, decompression and extracti=
on.
filename =3D action_dict[ 'target_filename' ]
@@ -227,10 +215,10 @@
if not os.path.exists( full_path_to_dir ):
os.makedirs( full_path_to_dir )
# The package has been down-loaded, so we can now perform =
all of the actions defined for building it.
- with lcd( dir ):
- for action_tup in filtered_actions:
+ for action_tup in filtered_actions:
+ current_dir =3D os.path.abspath( os.path.join( work_di=
r, dir ) )
+ with lcd( current_dir ):
action_type, action_dict =3D action_tup
- current_dir =3D os.path.abspath( os.path.join( wor=
k_dir, dir ) )
if action_type =3D=3D 'make_directory':
common_util.make_directory( full_path=3Daction=
_dict[ 'full_path' ] )
elif action_type =3D=3D 'move_directory_files':
@@ -316,13 +304,20 @@
if return_code:
return
elif action_type =3D=3D 'download_file':
- # Download a single file to the current direct=
ory.
+ # Download a single file to the current workin=
g directory.
url =3D action_dict[ 'url' ]
- if action_dict[ 'target_filename' ]:
+ if 'target_filename' in action_dict:
filename =3D action_dict[ 'target_filename=
' ]
else:
filename =3D url.split( '/' )[ -1 ]
- common_util.url_download( current_dir, filenam=
e, url )
+ extract =3D action_dict.get( 'extract', False )
+ common_util.url_download( current_dir, filenam=
e, url, extract=3Dextract )
+ elif action_type =3D=3D 'change_directory':
+ target_directory =3D os.path.realpath( os.path=
.join( current_dir, action_dict[ 'directory' ] ) )
+ if target_directory.startswith( os.path.realpa=
th( current_dir ) ) and os.path.exists( target_directory ):
+ dir =3D target_directory
+ else:
+ log.error( 'Invalid or nonexistent directo=
ry %s specified, ignoring change_directory action.', target_directory )
=20
def log_results( command, fabric_AttributeString, file_path ):
"""
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/tool_shed/galaxy_install/tool_dependencies/install_ut=
il.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
@@ -13,6 +13,7 @@
from tool_shed.util import xml_util
from galaxy.model.orm import and_
from galaxy.web import url_for
+from galaxy.util import asbool
=20
log =3D logging.getLogger( __name__ )
=20
@@ -390,15 +391,19 @@
# <action type=3D"download_by_url">http://sourceforge.net/proj=
ects/samtools/files/samtools/0.1.18/samtools-0.1.18.tar.bz2</action>
if action_elem.text:
action_dict[ 'url' ] =3D action_elem.text
- if 'target_filename' in action_elem.attrib:
- action_dict[ 'target_filename' ] =3D action_elem.attri=
b[ 'target_filename' ]
+ target_filename =3D action_elem.get( 'target_filename', No=
ne )
+ if target_filename:
+ action_dict[ 'target_filename' ] =3D target_filename
else:
continue
elif action_type =3D=3D 'download_file':
# <action type=3D"download_file">http://effectors.org/download=
/version/TTSS_GUI-1.0.1.jar</action>
if action_elem.text:
action_dict[ 'url' ] =3D action_elem.text
- action_dict[ 'target_filename' ] =3D action_elem.attrib.ge=
t( 'target_filename', None )
+ target_filename =3D action_elem.get( 'target_filename', No=
ne )
+ if target_filename:
+ action_dict[ 'target_filename' ] =3D target_filename
+ action_dict[ 'extract' ] =3D asbool( action_elem.get( 'ext=
ract', False ) )
else:
continue
elif action_type =3D=3D 'make_directory':
@@ -407,6 +412,12 @@
action_dict[ 'full_path' ] =3D evaluate_template( action_e=
lem.text )
else:
continue
+ elif action_type =3D=3D 'change_directory':
+ # <action type=3D"change_directory">PHYLIP-3.6b</action>
+ if action_elem.text:
+ action_dict[ 'directory' ] =3D action_elem.text
+ else:
+ continue
elif action_type in [ 'move_directory_files', 'move_file' ]:
# <action type=3D"move_file">
# <source>misc/some_file</source>
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/tool_shed/util/repository_dependency_util.py
--- a/lib/tool_shed/util/repository_dependency_util.py
+++ b/lib/tool_shed/util/repository_dependency_util.py
@@ -103,7 +103,6 @@
the dependency relationships between installed repositories. This met=
hod is called when new repositories are being installed into a Galaxy
instance and when uninstalled repositories are being reinstalled.
"""
- message =3D ''
# The following list will be maintained within this method to contain =
all created or updated tool shed repositories, including repository depende=
ncies
# that may not be installed.
all_created_or_updated_tool_shed_repositories =3D []
@@ -241,7 +240,7 @@
filtered_repo_info_dicts.append( repo_info_dict )
# Build repository dependency relationships even if the user chose to =
not install repository dependencies.
build_repository_dependency_relationships( trans, all_repo_info_dicts,=
all_created_or_updated_tool_shed_repositories )
- return created_or_updated_tool_shed_repositories, tool_panel_section_k=
eys, all_repo_info_dicts, filtered_repo_info_dicts, message
+ return created_or_updated_tool_shed_repositories, tool_panel_section_k=
eys, all_repo_info_dicts, filtered_repo_info_dicts
=20
def generate_message_for_invalid_repository_dependencies( metadata_dict ):
"""Return the error message associated with an invalid repository depe=
ndency for display in the caller."""
diff -r 46f4beebb766fd75edb59bc3598342ef95775af9 -r 1ff57c7a9debe0ced8bd216=
a33789218190f1f47 lib/tool_shed/util/tool_dependency_util.py
--- a/lib/tool_shed/util/tool_dependency_util.py
+++ b/lib/tool_shed/util/tool_dependency_util.py
@@ -220,9 +220,16 @@
=20
def get_tool_dependency_ids( as_string=3DFalse, **kwd ):
tool_dependency_id =3D kwd.get( 'tool_dependency_id', None )
- tool_dependency_ids =3D util.listify( kwd.get( 'tool_dependency_ids', =
None ) )
- if not tool_dependency_ids:
- tool_dependency_ids =3D util.listify( kwd.get( 'id', None ) )
+ if 'tool_dependency_ids' in kwd:
+ tool_dependency_ids =3D util.listify( kwd[ 'tool_dependency_ids' ]=
)
+ elif 'id' in kwd:
+ tool_dependency_ids =3D util.listify( kwd[ 'id' ] )
+ elif 'inst_td_ids' in kwd:
+ tool_dependency_ids =3D util.listify( kwd[ 'inst_td_ids' ] )
+ elif 'uninstalled_tool_dependency_ids' in kwd:
+ tool_dependency_ids =3D util.listify( kwd[ 'uninstalled_tool_depen=
dency_ids' ] )
+ else:
+ tool_dependency_ids =3D []
if tool_dependency_id and tool_dependency_id not in tool_dependency_id=
s:
tool_dependency_ids.append( tool_dependency_id )
if as_string:
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/galaxy/galaxy-central/commits/f1e5dfbbea46/
Changeset: f1e5dfbbea46
User: saketkc
Date: 2013-06-27 06:35:20
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 3fa9df444b4b81f94b1c42a033c685a6e23827be -r f1e5dfbbea46f0957ce4849=
4996444eb61f4a818 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/7e13235ae59a/
Changeset: 7e13235ae59a
User: saketkc
Date: 2013-06-28 07:00:22
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r b89b721a0b3db47cdeddef35f03ce4c2ffcb47b5 -r 7e13235ae59a1fb5eaa795c=
0797b4afa38001a38 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/8a88c559d596/
Changeset: 8a88c559d596
User: saketkc
Date: 2013-06-29 11:41:22
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 019ad31c3c2502005846dadc5c0457bbb6f80712 -r 8a88c559d5961d41c630b8e=
2dd1dafe6f275b9b2 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/13dc3f5865da/
Changeset: 13dc3f5865da
User: saketkc
Date: 2013-07-01 22:14:34
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 2cabbf3687634090fbbc024726f15f43db4ff314 -r 13dc3f5865da864c3823b31=
df455b5f6f1acb9f3 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/868bfd34f465/
Changeset: 868bfd34f465
User: saketkc
Date: 2013-07-09 10:41:15
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 86efa5ac1fae6fb46e7af9804e036a7ab44b0e26 -r 868bfd34f465dc1b6176d02=
fce93baecf3129279 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/f8c0c28b902e/
Changeset: f8c0c28b902e
User: saketkc
Date: 2013-07-10 21:30:38
Summary: vcfclass change merged
Affected #: 1 file
diff -r 4cc057df762c219406af27dd04ac725a07a5a6eb -r f8c0c28b902ecad5821ece5=
5030a9e7d02f779cf tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/4ff5c8a3ff34/
Changeset: 4ff5c8a3ff34
User: saketkc
Date: 2013-07-24 20:59:58
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r b42dfe74e237ea7f9c77059e427db92d9859bc67 -r 4ff5c8a3ff347824b430c99=
3303f2d97d907e2ed tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/28bad82d523b/
Changeset: 28bad82d523b
User: saketkc
Date: 2013-07-25 15:07:54
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 2abd0819d354d3d11182297c7206408d299f0d16 -r 28bad82d523b2053fa69c70=
301de69a74e57f323 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/a360e1b7b506/
Changeset: a360e1b7b506
User: saketkc
Date: 2013-07-31 15:48:50
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 951e853b0bcd2c62cedee0b95d46c9e36ab6c605 -r a360e1b7b506450385be74b=
2c6b7762d3e794bbd tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/79ae7df72fba/
Changeset: 79ae7df72fba
User: saketkc
Date: 2013-08-02 19:20:58
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 24 files
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c .hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -85,6 +85,7 @@
.coverage
htmlcov
run_unit_tests.html
+test/unit/**.log
=20
# Project files
*.kpf
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -475,6 +475,9 @@
=20
def sniff(self, filename):
try:
+ # All twobit files start with a 16-byte header. If the file is=
smaller than 16 bytes, it's obviously not a valid twobit file.
+ if os.path.getsize(filename) < 16:
+ return False
input =3D file(filename)
magic =3D struct.unpack(">L", input.read(TWOBIT_MAGIC_SIZE))[0]
if magic =3D=3D TWOBIT_MAGIC_NUMBER or magic =3D=3D TWOBIT_MAG=
IC_NUMBER_SWAP:
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -1514,8 +1514,8 @@
NOTE: This is wasteful since dynamic options and dataset collection
happens twice (here and when generating HTML).=20
"""
- # Can't look at history in workflow mode
- if trans is None or trans.workflow_building_mode:
+ # Can't look at history in workflow mode. Tool shed has no histori=
es.
+ if trans is None or trans.workflow_building_mode or trans.webapp.n=
ame =3D=3D 'tool_shed':
return DummyDataset()
assert trans is not None, "DataToolParameter requires a trans"
history =3D trans.get_history()
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c lib/galaxy/visualization/data_providers/genome.py
--- a/lib/galaxy/visualization/data_providers/genome.py
+++ b/lib/galaxy/visualization/data_providers/genome.py
@@ -13,6 +13,7 @@
from galaxy.util.json import from_json_string
from bx.interval_index_file import Indexes
from bx.bbi.bigwig_file import BigWigFile
+from bx.bbi.bigbed_file import BigBedFile
from galaxy.util.lrucache import LRUCache
from galaxy.visualization.data_providers.basic import BaseDataProvider
from galaxy.visualization.data_providers.cigar import get_ref_based_read_s=
eq_and_cigar
@@ -861,14 +862,14 @@
"""
Returns an iterator that provides data in the region chrom:start-e=
nd
"""
- start, end =3D int(start), int(end)
+ start, end =3D int( start ), int( end )
orig_data_filename =3D self.original_dataset.file_name
index_filename =3D self.converted_dataset.file_name
=20
# Attempt to open the BAM file with index
bamfile =3D csamtools.Samfile( filename=3Dorig_data_filename, mode=
=3D'rb', index_filename=3Dindex_filename )
try:
- data =3D bamfile.fetch(start=3Dstart, end=3Dend, reference=3Dc=
hrom)
+ data =3D bamfile.fetch( start=3Dstart, end=3Dend, reference=3D=
chrom )
except ValueError, e:
# Try alternative chrom naming.
chrom =3D _convert_between_ucsc_and_ensemble_naming( chrom )
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c lib/galaxy/webapps/galaxy/api/histories.py
--- a/lib/galaxy/webapps/galaxy/api/histories.py
+++ b/lib/galaxy/webapps/galaxy/api/histories.py
@@ -1,5 +1,7 @@
"""
API operations on a history.
+
+.. seealso:: :class:`galaxy.model.History`
"""
=20
import pkg_resources
@@ -21,17 +23,28 @@
@web.expose_api_anonymous
def index( self, trans, deleted=3D'False', **kwd ):
"""
- GET /api/histories
- GET /api/histories/deleted
- Displays a collection (list) of histories.
+ index( trans, deleted=3D'False' )
+ * GET /api/histories:
+ return undeleted histories for the current user
+ * GET /api/histories/deleted:
+ return deleted histories for the current user
+ .. note:: Anonymous users are allowed to get their current history
+
+ :type deleted: boolean
+ :param deleted: if True, show only deleted histories, if False, n=
on-deleted
+
+ :rtype: list
+ :returns: list of dictionaries containing summary history inform=
ation
"""
#TODO: query (by name, date, etc.)
rval =3D []
deleted =3D string_as_bool( deleted )
try:
if trans.user:
- query =3D trans.sa_session.query(trans.app.model.History )=
.filter_by( user=3Dtrans.user, deleted=3Ddeleted ).order_by(
- desc(trans.app.model.History.table.c.update_time)).all=
()
+ query =3D ( trans.sa_session.query( trans.app.model.Histor=
y )
+ .filter_by( user=3Dtrans.user, deleted=3Ddelet=
ed )
+ .order_by( desc( trans.app.model.History.table=
.c.update_time ) )
+ .all() )
for history in query:
item =3D history.get_api_value(value_mapper=3D{'id':tr=
ans.security.encode_id})
item['url'] =3D url_for( 'history', id=3Dtrans.securit=
y.encode_id( history.id ) )
@@ -52,11 +65,25 @@
=20
@web.expose_api_anonymous
def show( self, trans, id, deleted=3D'False', **kwd ):
+ # oh, sphinx - you bastard
"""
- GET /api/histories/{encoded_history_id}
- GET /api/histories/deleted/{encoded_history_id}
- GET /api/histories/most_recently_used
- Displays information about a history.
+ show( trans, id, deleted=3D'False' )
+ * GET /api/histories/{id}:
+ return the history with ``id``
+ * GET /api/histories/deleted/{id}:
+ return the deleted history with ``id``
+ * GET /api/histories/most_recently_used:
+ return the most recently used history
+ .. note:: Anonymous users are allowed to get their current history
+
+ :type id: an encoded id string
+ :param id: the encoded id of the history to query or the str=
ing 'most_recently_used'
+ :type deleted: boolean
+ :param deleted: if True, allow information on a deleted history t=
o be shown.
+
+ :rtype: dictionary
+ :returns: detailed history information from
+ :func:`galaxy.web.base.controller.UsesHistoryDatasetAssociatio=
nMixin.get_history_dict`
"""
#TODO: GET /api/histories/{encoded_history_id}?as_archive=3DTrue
#TODO: GET /api/histories/s/{username}/{slug}
@@ -94,8 +121,16 @@
@web.expose_api
def create( self, trans, payload, **kwd ):
"""
- POST /api/histories
- Creates a new history.
+ create( trans, payload )
+ * POST /api/histories:
+ create a new history
+
+ :type payload: dict
+ :param payload: (optional) dictionary structure containing:
+ * name: the new history's name
+ =20
+ :rtype: dict
+ :returns: element view of new history
"""
hist_name =3D None
if payload.get( 'name', None ):
@@ -115,8 +150,24 @@
@web.expose_api
def delete( self, trans, id, **kwd ):
"""
- DELETE /api/histories/{encoded_history_id}
- Deletes a history
+ delete( self, trans, id, **kwd )
+ * DELETE /api/histories/{id}
+ delete the history with the given ``id``
+ .. note:: Currently does not stop any active jobs in the history.
+
+ :type id: str
+ :param id: the encoded id of the history to delete
+ :type kwd: dict
+ :param kwd: (optional) dictionary structure containing:
+ =20
+ * payload: a dictionary itself containing:
+ * purge: if True, purge the history and all of it's HDAs
+
+ :rtype: dict
+ :returns: an error object if an error occurred or a dictionary c=
ontaining:
+ * id: the encoded id of the history,
+ * deleted: if the history was marked as deleted,
+ * purged: if the history was purged
"""
history_id =3D id
# a request body is optional here
@@ -175,8 +226,15 @@
@web.expose_api
def undelete( self, trans, id, **kwd ):
"""
- POST /api/histories/deleted/{encoded_history_id}/undelete
- Undeletes a history
+ undelete( self, trans, id, **kwd )
+ * POST /api/histories/deleted/{id}/undelete:
+ undelete history (that hasn't been purged) with the given ``id=
``
+
+ :type id: str
+ :param id: the encoded id of the history to undelete
+
+ :rtype: str
+ :returns: 'OK' if the history was undeleted
"""
history_id =3D id
history =3D self.get_history( trans, history_id, check_ownership=
=3DTrue, check_accessible=3DFalse, deleted=3DTrue )
@@ -188,8 +246,21 @@
@web.expose_api
def update( self, trans, id, payload, **kwd ):
"""
- PUT /api/histories/{encoded_history_id}
- Changes an existing history.
+ update( self, trans, id, payload, **kwd )
+ * PUT /api/histories/{id}
+ updates the values for the history with the given ``id``
+
+ :type id: str
+ :param id: the encoded id of the history to undelete
+ :type payload: dict
+ :param payload: a dictionary containing any or all the
+ fields in :func:`galaxy.model.History.get_api_value` and/or th=
e following:
+ =20
+ * annotation: an annotation for the history
+
+ :rtype: dict
+ :returns: an error object if an error occurred or a dictionary c=
ontaining
+ any values that were different from the original and, therefor=
e, updated
"""
#TODO: PUT /api/histories/{encoded_history_id} payload =3D { ratin=
g: rating } (w/ no security checks)
try:
@@ -255,6 +326,6 @@
raise ValueError( 'annotation must be a string or unic=
ode: %s' %( str( type( val ) ) ) )
validated_payload[ 'annotation' ] =3D sanitize_html( val, =
'utf-8' )
elif key not in valid_but_uneditable_keys:
- raise AttributeError( 'unknown key: %s' %( str( key ) ) )
+ pass
+ #log.warn( 'unknown key: %s', str( key ) )
return validated_payload
-
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c lib/galaxy/webapps/galaxy/api/history_contents.py
--- a/lib/galaxy/webapps/galaxy/api/history_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/history_contents.py
@@ -15,21 +15,27 @@
@web.expose_api_anonymous
def index( self, trans, history_id, ids=3DNone, **kwd ):
"""
- GET /api/histories/{encoded_history_id}/contents
- Displays a collection (list) of history contents (HDAs)
+ index( self, trans, history_id, ids=3DNone, **kwd )
+ * GET /api/histories/{history_id}/contents
+ return a list of HDA data for the history with the given ``id``
+ .. note:: Anonymous users are allowed to get their current history=
contents
=20
- :param history_id: an encoded id string of the `History` to search
- :param ids: (optional) a comma separated list of encoded `HDA` ids
-
- If Ids is not given, index returns a list of *summary* json object=
s for
- every `HDA` associated with the given `history_id`.
- See _summary_hda_dict.
+ If Ids is not given, index returns a list of *summary* objects for
+ every HDA associated with the given `history_id`.
=20
If ids is given, index returns a *more complete* json object for e=
ach
HDA in the ids list.
=20
- Note: Anonymous users are allowed to get their current history con=
tents
- (generally useful for browser UI access of the api)
+ :type history_id: str
+ :param history_id: encoded id string of the HDA's History
+ :type ids: str
+ :param ids: (optional) a comma separated list of encoded `=
HDA` ids
+
+ :rtype: list
+ :returns: dictionaries containing summary or detailed HDA inform=
ation
+ .. seealso::
+ :func:`_summary_hda_dict` and
+ :func:`galaxy.web.base.controller.UsesHistoryDatasetAssociatio=
nMixin.get_hda_dict`
"""
rval =3D []
try:
@@ -78,13 +84,13 @@
#TODO: move to model or Mixin
def _summary_hda_dict( self, trans, history_id, hda ):
"""
- Returns a dictionary based on the HDA in .. _summary form::
- {
- 'id' : < the encoded dataset id >,
- 'name' : < currently only returns 'file' >,
- 'type' : < name of the dataset >,
- 'url' : < api url to retrieve this datasets full data >,
- }
+ Returns a dictionary based on the HDA in summary form::
+ {
+ 'id' : < the encoded dataset id >,
+ 'name' : < currently only returns 'file' >,
+ 'type' : < name of the dataset >,
+ 'url' : < api url to retrieve this datasets full data >,
+ }
"""
api_type =3D "file"
encoded_id =3D trans.security.encode_id( hda.id )
@@ -98,8 +104,19 @@
@web.expose_api_anonymous
def show( self, trans, id, history_id, **kwd ):
"""
- GET /api/histories/{encoded_history_id}/contents/{encoded_content_=
id}
- Displays information about a history content (dataset).
+ show( self, trans, id, history_id, **kwd )
+ * GET /api/histories/{history_id}/contents/{id}
+ return detailed information about an HDA within a history
+ .. note:: Anonymous users are allowed to get their current history=
contents
+
+ :type id: str
+ :param ids: the encoded id of the HDA to return
+ :type history_id: str
+ :param history_id: encoded id string of the HDA's History
+
+ :rtype: dict
+ :returns: dictionary containing detailed HDA information
+ .. seealso:: :func:`galaxy.web.base.controller.UsesHistoryDatasetA=
ssociationMixin.get_hda_dict`
"""
hda_dict =3D {}
try:
@@ -135,8 +152,18 @@
@web.expose_api
def create( self, trans, history_id, payload, **kwd ):
"""
- POST /api/histories/{encoded_history_id}/contents
- Creates a new history content item (file, aka HistoryDatasetAssoci=
ation).
+ create( self, trans, history_id, payload, **kwd )
+ * POST /api/histories/{history_id}/contents
+ create a new HDA by copying an accessible LibraryDataset
+
+ :type history_id: str
+ :param history_id: encoded id string of the new HDA's History
+ :type payload: dict
+ :param payload: dictionary structure containing::
+ 'from_ld_id': the encoded id of the LibraryDataset to copy
+
+ :rtype: dict
+ :returns: dictionary containing detailed information for the new=
HDA
"""
#TODO: copy existing, accessible hda - dataset controller, copy_da=
tasets
#TODO: convert existing, accessible hda - model.DatasetInstance(or=
hda.datatype).get_converter_types
@@ -173,8 +200,24 @@
@web.expose_api
def update( self, trans, history_id, id, payload, **kwd ):
"""
- PUT /api/histories/{encoded_history_id}/contents/{encoded_content_=
id}
- Changes an existing history dataset.
+ update( self, trans, history_id, id, payload, **kwd )
+ * PUT /api/histories/{history_id}/contents/{id}
+ updates the values for the HDA with the given ``id``
+
+ :type history_id: str
+ :param history_id: encoded id string of the HDA's History
+ :type id: str
+ :param id: the encoded id of the history to undelete
+ :type payload: dict
+ :param payload: a dictionary containing any or all the
+ fields in :func:`galaxy.model.HistoryDatasetAssociation.get_ap=
i_value`
+ and/or the following:
+
+ * annotation: an annotation for the HDA
+
+ :rtype: dict
+ :returns: an error object if an error occurred or a dictionary c=
ontaining
+ any values that were different from the original and, therefor=
e, updated
"""
#TODO: PUT /api/histories/{encoded_history_id} payload =3D { ratin=
g: rating } (w/ no security checks)
changed =3D {}
@@ -251,6 +294,7 @@
raise ValueError( 'misc_info must be a string or unico=
de: %s' %( str( type( val ) ) ) )
validated_payload[ 'info' ] =3D util.sanitize_html.sanitiz=
e_html( val, 'utf-8' )
elif key not in valid_but_uneditable_keys:
- raise AttributeError( 'unknown key: %s' %( str( key ) ) )
+ pass
+ #log.warn( 'unknown key: %s', str( key ) )
return validated_payload
=20
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c lib/galaxy/webapps/galaxy/api/libraries.py
--- a/lib/galaxy/webapps/galaxy/api/libraries.py
+++ b/lib/galaxy/webapps/galaxy/api/libraries.py
@@ -15,9 +15,18 @@
@web.expose_api
def index( self, trans, deleted=3D'False', **kwd ):
"""
- GET /api/libraries
- GET /api/libraries/deleted
- Displays a collection (list) of libraries.
+ index( self, trans, deleted=3D'False', **kwd )
+ * GET /api/libraries:
+ returns a list of summary data for libraries
+ * GET /api/libraries/deleted:
+ returns a list of summary data for deleted libraries
+
+ :type deleted: boolean
+ :param deleted: if True, show only deleted libraries, if False, n=
on-deleted
+
+ :rtype: list
+ :returns: list of dictionaries containing library information
+ .. seealso:: :attr:`galaxy.model.Library.api_collection_visible_ke=
ys`
"""
log.debug( "LibrariesController.index: enter" )
query =3D trans.sa_session.query( trans.app.model.Library )
@@ -49,9 +58,20 @@
@web.expose_api
def show( self, trans, id, deleted=3D'False', **kwd ):
"""
- GET /api/libraries/{encoded_library_id}
- GET /api/libraries/deleted/{encoded_library_id}
- Displays information about a library.
+ show( self, trans, id, deleted=3D'False', **kwd )
+ * GET /api/libraries/{id}:
+ returns detailed information about a library
+ * GET /api/libraries/deleted/{id}:
+ returns detailed information about a deleted library
+
+ :type id: an encoded id string
+ :param id: the encoded id of the library
+ :type deleted: boolean
+ :param deleted: if True, allow information on a deleted library
+
+ :rtype: dictionary
+ :returns: detailed library information
+ .. seealso:: :attr:`galaxy.model.Library.api_element_visible_keys`
"""
log.debug( "LibraryContentsController.show: enter" )
library_id =3D id
@@ -75,8 +95,20 @@
@web.expose_api
def create( self, trans, payload, **kwd ):
"""
- POST /api/libraries
- Creates a new library.
+ create( self, trans, payload, **kwd )
+ * POST /api/libraries:
+ create a new library
+ .. note:: Currently, only admin users can create libraries.
+
+ :type payload: dict
+ :param payload: (optional) dictionary structure containing::
+ 'name': the new library's name
+ 'description': the new library's description
+ 'synopsis': the new library's synopsis
+
+ :rtype: dict
+ :returns: a dictionary containing the id, name, and 'show' url
+ of the new library
"""
if not trans.user_is_admin():
raise HTTPForbidden( detail=3D'You are not authorized to creat=
e a new library.' )
@@ -102,6 +134,19 @@
=20
@web.expose_api
def delete( self, trans, id, **kwd ):
+ """
+ delete( self, trans, id, **kwd )
+ * DELETE /api/histories/{id}
+ mark the library with the given ``id`` as deleted
+ .. note:: Currently, only admin users can delete libraries.
+
+ :type id: str
+ :param id: the encoded id of the library to delete
+
+ :rtype: dictionary
+ :returns: detailed library information
+ .. seealso:: :attr:`galaxy.model.Library.api_element_visible_keys`
+ """
if not trans.user_is_admin():
raise HTTPForbidden( detail=3D'You are not authorized to delet=
e libraries.' )
try:
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c lib/galaxy/webapps/galaxy/api/library_contents.py
--- a/lib/galaxy/webapps/galaxy/api/library_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/library_contents.py
@@ -19,8 +19,21 @@
# TODO: Add parameter to only get top level of datasets/subfolders.
def index( self, trans, library_id, **kwd ):
"""
- GET /api/libraries/{encoded_library_id}/contents
- Displays a collection (list) of library contents (files and folder=
s).
+ index( self, trans, library_id, **kwd )
+ * GET /api/libraries/{library_id}/contents:
+ return a list of library files and folders
+
+ :type library_id: str
+ :param library_id: encoded id string of the library that contains=
this item
+
+ :rtype: list
+ :returns: list of dictionaries of the form:
+
+ * id: the encoded id of the library item
+ * name: the 'libary path'
+ or relationship of the library item to the root
+ * type: 'file' or 'folder'
+ * url: the url to get detailed information on the library item
"""
rval =3D []
current_user_roles =3D trans.get_current_user_roles()
@@ -80,8 +93,20 @@
@web.expose_api
def show( self, trans, id, library_id, **kwd ):
"""
- GET /api/libraries/{encoded_library_id}/contents/{encoded_content_=
id}
- Displays information about a library content (file or folder).
+ show( self, trans, id, library_id, **kwd )
+ * GET /api/libraries/{library_id}/contents/{id}
+ return information about library file or folder
+
+ :type id: str
+ :param id: the encoded id of the library item to return
+ :type library_id: str
+ :param library_id: encoded id string of the library that contains=
this item
+
+ :rtype: dict
+ :returns: detailed library item information
+ .. seealso::
+ :func:`galaxy.model.LibraryDataset.get_api_value` and
+ :attr:`galaxy.model.LibraryFolder.api_element_visible_keys`
"""
class_name, content_id =3D self.__decode_library_content_id( trans=
, id )
if class_name =3D=3D 'LibraryFolder':
@@ -93,8 +118,29 @@
@web.expose_api
def create( self, trans, library_id, payload, **kwd ):
"""
- POST /api/libraries/{encoded_library_id}/contents
- Creates a new library content item (file or folder).
+ create( self, trans, library_id, payload, **kwd )
+ * POST /api/libraries/{library_id}/contents:
+ create a new library file or folder
+
+ To copy an HDA into a library send ``create_type`` of 'file' and
+ the HDA's encoded id in ``from_hda_id`` (and optionally ``ldda_mes=
sage``).
+
+ :type library_id: str
+ :param library_id: encoded id string of the library that contains=
this item
+ :type payload: dict
+ :param payload: dictionary structure containing:
+ =20
+ * folder_id: the parent folder of the new item
+ * create_type: the type of item to create ('file' or 'folder')
+ * from_hda_id: (optional) the id of an accessible HDA to copy=
into the
+ library
+ * ldda_message: (optional) the new message attribute of the LD=
DA created
+ * extended_metadata: (optional) dub-dictionary containing any =
extended
+ metadata to associate with the item
+
+ :rtype: dict
+ :returns: a dictionary containing the id, name,
+ and 'show' url of the new item
"""
create_type =3D None
if 'create_type' not in payload:
@@ -195,10 +241,10 @@
=20
def _copy_hda_to_library_folder( self, trans, from_hda_id, library_id,=
folder_id, ldda_message=3D'' ):
"""
- Copies hda `from_hda_id` to library folder `library_folder_id` opt=
ionally
- adding `ldda_message` to the new ldda's `message`.
+ Copies hda ``from_hda_id`` to library folder ``library_folder_id``=
optionally
+ adding ``ldda_message`` to the new ldda's ``message``.
=20
- `library_contents.create` will branch to this if called with 'from=
_hda_id'
+ ``library_contents.create`` will branch to this if called with 'fr=
om_hda_id'
in it's payload.
"""
log.debug( '_copy_hda_to_library_folder: %s' %( str(( from_hda_id,=
library_id, folder_id, ldda_message )) ) )
@@ -236,10 +282,23 @@
return rval
=20
@web.expose_api
- def update( self, trans, id, library_id, payload, **kwd ):
+ def update( self, trans, id, library_id, payload, **kwd ):
"""
- PUT /api/libraries/{encoded_library_id}/contents/{encoded_content_=
type_and_id}
- Sets relationships among items
+ update( self, trans, id, library_id, payload, **kwd )
+ * PUT /api/libraries/{library_id}/contents/{id}
+ create a ImplicitlyConvertedDatasetAssociation
+ .. seealso:: :class:`galaxy.model.ImplicitlyConvertedDatasetAssoci=
ation`
+
+ :type id: str
+ :param id: the encoded id of the library item to return
+ :type library_id: str
+ :param library_id: encoded id string of the library that contains=
this item
+ :type payload: dict
+ :param payload: dictionary structure containing::
+ 'converted_dataset_id':
+
+ :rtype: None
+ :returns: None
"""
if 'converted_dataset_id' in payload:
converted_id =3D payload.pop( 'converted_dataset_id' )
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c lib/tool_shed/galaxy_install/tool_dependencies/common_uti=
l.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/common_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/common_util.py
@@ -8,6 +8,7 @@
import zipfile
import tool_shed.util.shed_util_common as suc
from galaxy.datatypes import checkers
+from urllib2 import HTTPError
=20
log =3D logging.getLogger( __name__ )
=20
@@ -70,6 +71,23 @@
__shellquote(env_shell_file_path=
))
return cmd
=20
+def download_binary_from_url( url, work_dir, install_dir ):
+ '''
+ Download a pre-compiled binary from the specified URL. If the download=
ed file is an archive,
+ extract it into install_dir and delete the archive.
+ '''
+ downloaded_filename =3D os.path.split( url )[ -1 ]
+ try:
+ dir =3D url_download( work_dir, downloaded_filename, url, extract=
=3DTrue )
+ downloaded_filepath =3D os.path.join( work_dir, downloaded_filenam=
e )
+ if is_compressed( downloaded_filepath ):
+ os.remove( downloaded_filepath )
+ move_directory_files( current_dir=3Dwork_dir,
+ source_dir=3Ddir,
+ destination_dir=3Dinstall_dir )
+ return True
+ except HTTPError:
+ return False
=20
def extract_tar( file_name, file_path ):
if isgzip( file_name ) or isbz2( file_name ):
@@ -190,6 +208,12 @@
def iszip( file_path ):
return checkers.check_zip( file_path )
=20
+def is_compressed( file_path ):
+ if isjar( file_path ):
+ return False
+ else:
+ return iszip( file_path ) or isgzip( file_path ) or istar( file_pa=
th ) or isbz2( file_path )
+
def make_directory( full_path ):
if not os.path.exists( full_path ):
os.makedirs( full_path )
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c lib/tool_shed/galaxy_install/tool_dependencies/fabric_uti=
l.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -165,12 +165,29 @@
actions =3D actions_dict.get( 'actions', None )
filtered_actions =3D []
env_shell_file_paths =3D []
+ # Default to false so that the install process will default to compili=
ng.
+ binary_found =3D False
if actions:
with make_tmp_dir() as work_dir:
with lcd( work_dir ):
# The first action in the list of actions will be the one =
that defines the installation process. There
# are currently only two supported processes; download_by_=
url and clone via a "shell_command" action type.
action_type, action_dict =3D actions[ 0 ]
+ if action_type =3D=3D 'download_binary':
+ # Eliminate the download_binary action so remaining ac=
tions can be processed correctly.
+ filtered_actions =3D actions[ 1: ]
+ url =3D action_dict[ 'url' ]
+ # Attempt to download a binary from the specified URL.
+ log.debug( 'Attempting to download from %s', url )
+ binary_found =3D common_util.download_binary_from_url(=
url, work_dir, install_dir )
+ if binary_found:
+ # If the attempt succeeded, set the action_type to=
binary_found, in order to skip any download_by_url or shell_command action=
s.
+ actions =3D filtered_actions
+ action_type =3D 'binary_found'
+ else:
+ # No binary exists, or there was an error download=
ing the binary from the generated URL. Proceed with the remaining actions.
+ del actions[ 0 ]
+ action_type, action_dict =3D actions[ 0 ]
if action_type =3D=3D 'download_by_url':
# Eliminate the download_by_url action so remaining ac=
tions can be processed correctly.
filtered_actions =3D actions[ 1: ]
@@ -220,6 +237,9 @@
current_dir =3D os.path.abspath( os.path.join( work_di=
r, dir ) )
with lcd( current_dir ):
action_type, action_dict =3D action_tup
+ # If a binary was found, we only need to process e=
nvironment variables, file permissions, and any other binary downloads.
+ if binary_found and action_type not in [ 'set_envi=
ronment', 'chmod', 'download_binary' ]:
+ continue
if action_type =3D=3D 'make_directory':
common_util.make_directory( full_path=3Daction=
_dict[ 'full_path' ] )
elif action_type =3D=3D 'move_directory_files':
@@ -348,6 +368,18 @@
dir =3D target_directory.replace( os.path.=
realpath( work_dir ), '' ).lstrip( '/' )
else:
log.error( 'Invalid or nonexistent directo=
ry %s specified, ignoring change_directory action.', target_directory )
+ elif action_type =3D=3D 'chmod':
+ for target_file, mode in action_dict[ 'change_=
modes' ]:
+ if os.path.exists( target_file ):
+ os.chmod( target_file, mode )
+ elif action_type =3D=3D 'download_binary':
+ url =3D action_dict[ 'url' ]
+ binary_found =3D common_util.download_binary_f=
rom_url( url, work_dir, install_dir )
+ if binary_found:
+ log.debug( 'Successfully downloaded binary=
from %s', url )
+ else:
+ log.error( 'Unable to download binary from=
%s', url )
+ =20
=20
def log_results( command, fabric_AttributeString, file_path ):
"""
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c lib/tool_shed/galaxy_install/tool_dependencies/install_ut=
il.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
@@ -1,6 +1,7 @@
import logging
import os
import sys
+import stat
import subprocess
import tempfile
from string import Template
@@ -379,7 +380,22 @@
for action_elem in actions_elem.findall( 'action' ):
action_dict =3D {}
action_type =3D action_elem.get( 'type', 'shell_command' )
- if action_type =3D=3D 'shell_command':
+ if action_type =3D=3D 'download_binary':
+ platform_info_dict =3D tool_dependency_util.get_platform_info_=
dict()
+ platform_info_dict[ 'name' ] =3D tool_dependency.name
+ platform_info_dict[ 'version' ] =3D tool_dependency.version
+ url_template_elems =3D action_elem.findall( 'url_template' )
+ # Check if there are multiple url_template elements, each with=
attrib entries for a specific platform.
+ if len( url_template_elems ) > 1:
+ # <base_url os=3D"darwin" extract=3D"false">http://hgdownl=
oad.cse.ucsc.edu/admin/exe/macOSX.${architecture}/faToTwoBit</base_url>
+ # This method returns the url_elem that best matches the c=
urrent platform as received from os.uname().
+ # Currently checked attributes are os and architecture.
+ # These correspond to the values sysname and processor fro=
m the Python documentation for os.uname().
+ url_template_elem =3D tool_dependency_util.get_download_ur=
l_for_platform( url_template_elems, platform_info_dict )
+ else:
+ url_template_elem =3D url_template_elems[ 0 ]
+ action_dict[ 'url' ] =3D Template( url_template_elem.text ).sa=
fe_substitute( platform_info_dict )
+ elif action_type =3D=3D 'shell_command':
# <action type=3D"shell_command">make</action>
action_elem_text =3D evaluate_template( action_elem.text )
if action_elem_text:
@@ -492,6 +508,27 @@
# lxml=3D=3D2.3.0</action>
## Manually specify contents of requirements.txt file to creat=
e dynamically.
action_dict[ 'requirements' ] =3D evaluate_template( action_el=
em.text or 'requirements.txt' )
+ elif action_type =3D=3D 'chmod':
+ # Change the read, write, and execute bits on a file.
+ file_elems =3D action_elem.findall( 'file' )
+ chmod_actions =3D []
+ # A unix octal mode is the sum of the following values:
+ # Owner:
+ # 400 Read 200 Write 100 Execute
+ # Group:
+ # 040 Read 020 Write 010 Execute
+ # World:
+ # 004 Read 002 Write 001 Execute
+ for file_elem in file_elems:
+ # So by the above table, owner read/write/execute and grou=
p read permission would be 740.
+ # Python's os.chmod uses base 10 modes, convert received u=
nix-style octal modes to base 10.
+ received_mode =3D int( file_elem.get( 'mode', 600 ), base=
=3D8 )
+ # For added security, ensure that the setuid and setgid bi=
ts are not set.
+ mode =3D received_mode & ~( stat.S_ISUID | stat.S_ISGID )
+ file =3D evaluate_template( file_elem.text )
+ chmod_tuple =3D ( file, mode )
+ chmod_actions.append( chmod_tuple )
+ action_dict[ 'change_modes' ] =3D chmod_actions
else:
log.debug( "Unsupported action type '%s'. Not proceeding." % s=
tr( action_type ) )
raise Exception( "Unsupported action type '%s' in tool depende=
ncy definition." % str( action_type ) )
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c lib/tool_shed/util/tool_dependency_util.py
--- a/lib/tool_shed/util/tool_dependency_util.py
+++ b/lib/tool_shed/util/tool_dependency_util.py
@@ -39,6 +39,37 @@
tool_dependencies[ dependency_key ] =3D requirements_dict
return tool_dependencies
=20
+def get_download_url_for_platform( url_templates, platform_info_dict ):
+ '''
+ Compare the dict returned by get_platform_info() with the values speci=
fied in the base_url element. Return
+ true if and only if all defined attributes match the corresponding dic=
t entries. If an entry is not
+ defined in the base_url element, it is assumed to be irrelevant at thi=
s stage. For example,
+ <base_url os=3D"darwin">http://hgdownload.cse.ucsc.edu/admin/exe/macOS=
X.${architecture}/faToTwoBit</base_url>
+ where the OS must be 'darwin', but the architecture is filled in later=
using string.Template.
+ '''
+ os_ok =3D False
+ architecture_ok =3D False
+ for url_template in url_templates:
+ os_name =3D url_template.get( 'os', None )
+ architecture =3D url_template.get( 'architecture', None )
+ if os_name:
+ if os_name.lower() =3D=3D platform_info_dict[ 'os' ]:
+ os_ok =3D True
+ else:
+ os_ok =3D False
+ else:
+ os_ok =3D True
+ if architecture:
+ if architecture.lower() =3D=3D platform_info_dict[ 'architectu=
re' ]:
+ architecture_ok =3D True
+ else:
+ architecture_ok =3D False
+ else:
+ architecture_ok =3D True
+ if os_ok and architecture_ok:
+ return url_template
+ return None
+
def create_or_update_tool_dependency( app, tool_shed_repository, name, ver=
sion, type, status, set_status=3DTrue ):
# Called from Galaxy (never the tool shed) when a new repository is be=
ing installed or when an uninstalled repository is being reinstalled.
sa_session =3D app.model.context.current
@@ -204,6 +235,14 @@
missing_tool_dependencies =3D None
return tool_dependencies, missing_tool_dependencies
=20
+def get_platform_info_dict():
+ '''Return a dict with information about the current platform.'''
+ platform_dict =3D {}
+ sysname, nodename, release, version, machine =3D os.uname()
+ platform_dict[ 'os' ] =3D sysname.lower()
+ platform_dict[ 'architecture' ] =3D machine.lower()
+ return platform_dict
+
def get_tool_dependency( trans, id ):
"""Get a tool_dependency from the database via id"""
return trans.sa_session.query( trans.model.ToolDependency ).get( trans=
.security.decode_id( id ) )
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c static/scripts/galaxy.pages.js
--- a/static/scripts/galaxy.pages.js
+++ b/static/scripts/galaxy.pages.js
@@ -164,18 +164,19 @@
{
"Make link": function() {
// Get URL, name/title.
- var sUrl =3D $(wym._options.hrefSelector).val(),
- sName =3D $(".wym_title").val();
+ var sUrl =3D $(wym._options.hrefSelector).val() || '',
+ sId =3D $(".wym_id").val() || '',
+ sName =3D $(wym._options.titleSelector).val() || '=
';
=20
- if (sUrl && sName) {
+ if (sUrl || sId) {
// Create link.
wym._exec(WYMeditor.CREATE_LINK, sStamp);
=20
// Set link attributes.
var link =3D $("a[href=3D" + sStamp + "]", wym._do=
c.body);
link.attr(WYMeditor.HREF, sUrl)
- .attr(WYMeditor.TITLE, $(wym._options.titleSel=
ector).val())
- .attr("id", sName);
+ .attr(WYMeditor.TITLE, sName)
+ .attr("id", sId);
=20
// If link's text is default (wym-...), change it =
to the title.
if (link.text().indexOf('wym-') =3D=3D=3D 0) {
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c static/scripts/packed/galaxy.pages.js
--- a/static/scripts/packed/galaxy.pages.js
+++ b/static/scripts/packed/galaxy.pages.js
@@ -1,1 +1,1 @@
-var Galaxy=3D{ITEM_HISTORY:"item_history",ITEM_DATASET:"item_dataset",ITEM=
_WORKFLOW:"item_workflow",ITEM_PAGE:"item_page",ITEM_VISUALIZATION:"item_vi=
sualization",DIALOG_HISTORY_LINK:"link_history",DIALOG_DATASET_LINK:"link_d=
ataset",DIALOG_WORKFLOW_LINK:"link_workflow",DIALOG_PAGE_LINK:"link_page",D=
IALOG_VISUALIZATION_LINK:"link_visualization",DIALOG_EMBED_HISTORY:"embed_h=
istory",DIALOG_EMBED_DATASET:"embed_dataset",DIALOG_EMBED_WORKFLOW:"embed_w=
orkflow",DIALOG_EMBED_PAGE:"embed_page",DIALOG_EMBED_VISUALIZATION:"embed_v=
isualization",DIALOG_HISTORY_ANNOTATE:"history_annotate",};function init_ga=
laxy_elts(a){$(".annotation",a._doc.body).each(function(){$(this).click(fun=
ction(){var b=3Da._doc.createRange();b.selectNodeContents(this);var d=3Dwin=
dow.getSelection();d.removeAllRanges();d.addRange(b);var c=3D""})})}functio=
n get_item_info(d){var f,c,b;switch(d){case (Galaxy.ITEM_HISTORY):f=3D"Hist=
ory";c=3D"Histories";b=3D"history";item_class=3D"History";break;case (Galax=
y.ITEM_DATASET):f=3D"Dataset";c=3D"Datasets";b=3D"dataset";item_class=3D"Hi=
storyDatasetAssociation";break;case (Galaxy.ITEM_WORKFLOW):f=3D"Workflow";c=
=3D"Workflows";b=3D"workflow";item_class=3D"StoredWorkflow";break;case (Gal=
axy.ITEM_PAGE):f=3D"Page";c=3D"Pages";b=3D"page";item_class=3D"Page";break;=
case (Galaxy.ITEM_VISUALIZATION):f=3D"Visualization";c=3D"Visualizations";b=
=3D"visualization";item_class=3D"Visualization";break}var e=3D"list_"+c.toL=
owerCase()+"_for_selection";var a=3Dlist_objects_url.replace("LIST_ACTION",=
e);return{singular:f,plural:c,controller:b,iclass:item_class,list_ajax_url:=
a}}function make_item_importable(a,c,b){ajax_url=3Dset_accessible_url.repla=
ce("ITEM_CONTROLLER",a);$.ajax({type:"POST",url:ajax_url,data:{id:c,accessi=
ble:"True"},error:function(){alert("Making "+b+" accessible failed")}})}WYM=
editor.editor.prototype.dialog=3Dfunction(i,e,g){var a=3Dthis;var b=3Da.uni=
queStamp();var f=3Da.selected();function h(){$("#set_link_id").click(functi=
on(){$("#link_attribute_label").text("ID/Name");var k=3D$(".wym_href");k.ad=
dClass("wym_id").removeClass("wym_href");if(f){k.val($(f).attr("id"))}$(thi=
s).remove()})}if(i=3D=3DWYMeditor.DIALOG_LINK){if(f){$(a._options.hrefSelec=
tor).val($(f).attr(WYMeditor.HREF));$(a._options.srcSelector).val($(f).attr=
(WYMeditor.SRC));$(a._options.titleSelector).val($(f).attr(WYMeditor.TITLE)=
);$(a._options.altSelector).val($(f).attr(WYMeditor.ALT))}var c,d;if(f){c=
=3D$(f).attr("href");if(c=3D=3Dundefined){c=3D""}d=3D$(f).attr("title");if(=
d=3D=3Dundefined){d=3D""}}show_modal("Create Link","<div><div><label id=3D'=
link_attribute_label'>URL <span style=3D'float: right; font-size: 90%'><a h=
ref=3D'#' id=3D'set_link_id'>Create in-page anchor</a></span></label><br><i=
nput type=3D'text' class=3D'wym_href' value=3D'"+c+"' size=3D'40' /></div><=
div><label>Title</label><br><input type=3D'text' class=3D'wym_title' value=
=3D'"+d+"' size=3D'40' /></div><div>",{"Make link":function(){var l=3D$(a._=
options.hrefSelector).val(),m=3D$(".wym_title").val();if(l&&m){a._exec(WYMe=
ditor.CREATE_LINK,b);var k=3D$("a[href=3D"+b+"]",a._doc.body);k.attr(WYMedi=
tor.HREF,l).attr(WYMeditor.TITLE,$(a._options.titleSelector).val()).attr("i=
d",m);if(k.text().indexOf("wym-")=3D=3D=3D0){k.text(m)}}hide_modal()},Cance=
l:function(){hide_modal()}},{},h)}if(i=3D=3DWYMeditor.DIALOG_IMAGE){if(a._s=
elected_image){$(a._options.dialogImageSelector+" "+a._options.srcSelector)=
.val($(a._selected_image).attr(WYMeditor.SRC));$(a._options.dialogImageSele=
ctor+" "+a._options.titleSelector).val($(a._selected_image).attr(WYMeditor.=
TITLE));$(a._options.dialogImageSelector+" "+a._options.altSelector).val($(=
a._selected_image).attr(WYMeditor.ALT))}show_modal("Image","<div class=3D'r=
ow'><label>URL</label><br><input type=3D'text' class=3D'wym_src' value=3D''=
size=3D'40' /></div><div class=3D'row'><label>Alt text</label><br><input t=
ype=3D'text' class=3D'wym_alt' value=3D'' size=3D'40' /></div><div class=3D=
'row'><label>Title</label><br><input type=3D'text' class=3D'wym_title' valu=
e=3D'' size=3D'40' /></div>",{Insert:function(){var k=3D$(a._options.srcSel=
ector).val();if(k.length>0){a._exec(WYMeditor.INSERT_IMAGE,b);$("img[src$=
=3D"+b+"]",a._doc.body).attr(WYMeditor.SRC,k).attr(WYMeditor.TITLE,$(a._opt=
ions.titleSelector).val()).attr(WYMeditor.ALT,$(a._options.altSelector).val=
())}hide_modal()},Cancel:function(){hide_modal()}});return}if(i=3D=3DWYMedi=
tor.DIALOG_TABLE){show_modal("Table","<div class=3D'row'><label>Caption</la=
bel><br><input type=3D'text' class=3D'wym_caption' value=3D'' size=3D'40' /=
></div><div class=3D'row'><label>Summary</label><br><input type=3D'text' cl=
ass=3D'wym_summary' value=3D'' size=3D'40' /></div><div class=3D'row'><labe=
l>Number Of Rows<br></label><input type=3D'text' class=3D'wym_rows' value=
=3D'3' size=3D'3' /></div><div class=3D'row'><label>Number Of Cols<br></lab=
el><input type=3D'text' class=3D'wym_cols' value=3D'2' size=3D'3' /></div>"=
,{Insert:function(){var o=3D$(a._options.rowsSelector).val();var r=3D$(a._o=
ptions.colsSelector).val();if(o>0&&r>0){var n=3Da._doc.createElement(WYMedi=
tor.TABLE);var l=3Dnull;var q=3Dnull;var k=3D$(a._options.captionSelector).=
val();var p=3Dn.createCaption();p.innerHTML=3Dk;for(x=3D0;x<o;x++){l=3Dn.in=
sertRow(x);for(y=3D0;y<r;y++){l.insertCell(y)}}$(n).attr("summary",$(a._opt=
ions.summarySelector).val());var m=3D$(a.findUp(a.container(),WYMeditor.MAI=
N_CONTAINERS)).get(0);if(!m||!m.parentNode){$(a._doc.body).append(n)}else{$=
(m).after(n)}}hide_modal()},Cancel:function(){hide_modal()}})}if(i=3D=3DGal=
axy.DIALOG_HISTORY_LINK||i=3D=3DGalaxy.DIALOG_DATASET_LINK||i=3D=3DGalaxy.D=
IALOG_WORKFLOW_LINK||i=3D=3DGalaxy.DIALOG_PAGE_LINK||i=3D=3DGalaxy.DIALOG_V=
ISUALIZATION_LINK){var j;switch(i){case (Galaxy.DIALOG_HISTORY_LINK):j=3Dge=
t_item_info(Galaxy.ITEM_HISTORY);break;case (Galaxy.DIALOG_DATASET_LINK):j=
=3Dget_item_info(Galaxy.ITEM_DATASET);break;case (Galaxy.DIALOG_WORKFLOW_LI=
NK):j=3Dget_item_info(Galaxy.ITEM_WORKFLOW);break;case (Galaxy.DIALOG_PAGE_=
LINK):j=3Dget_item_info(Galaxy.ITEM_PAGE);break;case (Galaxy.DIALOG_VISUALI=
ZATION_LINK):j=3Dget_item_info(Galaxy.ITEM_VISUALIZATION);break}$.ajax({url=
:j.list_ajax_url,data:{},error:function(){alert("Failed to list "+j.plural.=
toLowerCase()+" for selection")},success:function(k){show_modal("Insert Lin=
k to "+j.singular,k+"<div><input id=3D'make-importable' type=3D'checkbox' c=
hecked/>Make the selected "+j.plural.toLowerCase()+" accessible so that the=
y can viewed by everyone.</div>",{Insert:function(){var m=3Dfalse;if($("#ma=
ke-importable:checked").val()!=3D=3Dnull){m=3Dtrue}var l=3Dnew Array();$("i=
nput[name=3Did]:checked").each(function(){var n=3D$(this).val();if(m){make_=
item_importable(j.controller,n,j.singular)}url_template=3Dget_name_and_link=
_url+n;ajax_url=3Durl_template.replace("ITEM_CONTROLLER",j.controller);$.ge=
tJSON(ajax_url,function(p){a._exec(WYMeditor.CREATE_LINK,b);var o=3D$("a[hr=
ef=3D"+b+"]",a._doc.body).text();if(o=3D=3D""||o=3D=3Db){a.insert("<a href=
=3D'"+p.link+"'>"+j.singular+" '"+p.name+"'</a>")}else{$("a[href=3D"+b+"]",=
a._doc.body).attr(WYMeditor.HREF,p.link).attr(WYMeditor.TITLE,j.singular+n)=
}})});hide_modal()},Cancel:function(){hide_modal()}})}})}if(i=3D=3DGalaxy.D=
IALOG_EMBED_HISTORY||i=3D=3DGalaxy.DIALOG_EMBED_DATASET||i=3D=3DGalaxy.DIAL=
OG_EMBED_WORKFLOW||i=3D=3DGalaxy.DIALOG_EMBED_PAGE||i=3D=3DGalaxy.DIALOG_EM=
BED_VISUALIZATION){var j;switch(i){case (Galaxy.DIALOG_EMBED_HISTORY):j=3Dg=
et_item_info(Galaxy.ITEM_HISTORY);break;case (Galaxy.DIALOG_EMBED_DATASET):=
j=3Dget_item_info(Galaxy.ITEM_DATASET);break;case (Galaxy.DIALOG_EMBED_WORK=
FLOW):j=3Dget_item_info(Galaxy.ITEM_WORKFLOW);break;case (Galaxy.DIALOG_EMB=
ED_PAGE):j=3Dget_item_info(Galaxy.ITEM_PAGE);break;case (Galaxy.DIALOG_EMBE=
D_VISUALIZATION):j=3Dget_item_info(Galaxy.ITEM_VISUALIZATION);break}$.ajax(=
{url:j.list_ajax_url,data:{},error:function(){alert("Failed to list "+j.plu=
ral.toLowerCase()+" for selection")},success:function(k){if(i=3D=3DGalaxy.D=
IALOG_EMBED_HISTORY||i=3D=3DGalaxy.DIALOG_EMBED_WORKFLOW||i=3D=3DGalaxy.DIA=
LOG_EMBED_VISUALIZATION){k=3Dk+"<div><input id=3D'make-importable' type=3D'=
checkbox' checked/>Make the selected "+j.plural.toLowerCase()+" accessible =
so that they can viewed by everyone.</div>"}show_modal("Embed "+j.plural,k,=
{Embed:function(){var l=3Dfalse;if($("#make-importable:checked").val()!=3Dn=
ull){l=3Dtrue}$("input[name=3Did]:checked").each(function(){var m=3D$(this)=
.val();var p=3D$("label[for=3D'"+m+"']:first").text();if(l){make_item_impor=
table(j.controller,m,j.singular)}var n=3Dj.iclass+"-"+m;var o=3D"<p><div id=
=3D'"+n+"' class=3D'embedded-item "+j.singular.toLowerCase()+" placeholder'=
><p class=3D'title'>Embedded Galaxy "+j.singular+" '"+p+"'</p><p class=3D'c=
ontent'> [Do not edit this bloc=
k; Galaxy will fill it in with the annotated "+j.singular.toLowerCase()+" w=
hen it is displayed.] </p></div></p=
>";a.insert(" ");a.insert(o);$("#"+n,a._doc.body).each(function(){var =
q=3Dtrue;while(q){var r=3D$(this).prev();if(r.length!=3D0&&jQuery.trim(r.te=
xt())=3D=3D""){r.remove()}else{q=3Dfalse}}})});hide_modal()},Cancel:functio=
n(){hide_modal()}})}})}if(i=3D=3DGalaxy.DIALOG_ANNOTATE_HISTORY){$.ajax({ur=
l:list_histories_for_selection_url,data:{},error:function(){alert("Grid ref=
resh failed")},success:function(k){show_modal("Insert Link to History",k,{A=
nnotate:function(){var l=3Dnew Array();$("input[name=3Did]:checked").each(f=
unction(){var m=3D$(this).val();$.ajax({url:get_history_annotation_table_ur=
l,data:{id:m},error:function(){alert("Grid refresh failed")},success:functi=
on(n){a.insert(n);init_galaxy_elts(a)}})});hide_modal()},Cancel:function(){=
hide_modal()}})}})}};$(function(){$(document).ajaxError(function(i,g){var h=
=3Dg.responseText||g.statusText||"Could not connect to server";show_modal("=
Server error",h,{"Ignore error":hide_modal});return false});$("[name=3Dpage=
_content]").wymeditor({skin:"galaxy",basePath:editor_base_path,iframeBasePa=
th:iframe_base_path,boxHtml:"<table class=3D'wym_box' width=3D'100%' height=
=3D'100%'><tr><td><div class=3D'wym_area_top'>"+WYMeditor.TOOLS+"</div></td=
></tr><tr height=3D'100%'><td><div class=3D'wym_area_main' style=3D'height:=
100%;'>"+WYMeditor.IFRAME+WYMeditor.STATUS+"</div></div></td></tr></table>=
",toolsItems:[{name:"Bold",title:"Strong",css:"wym_tools_strong"},{name:"It=
alic",title:"Emphasis",css:"wym_tools_emphasis"},{name:"Superscript",title:=
"Superscript",css:"wym_tools_superscript"},{name:"Subscript",title:"Subscri=
pt",css:"wym_tools_subscript"},{name:"InsertOrderedList",title:"Ordered_Lis=
t",css:"wym_tools_ordered_list"},{name:"InsertUnorderedList",title:"Unorder=
ed_List",css:"wym_tools_unordered_list"},{name:"Indent",title:"Indent",css:=
"wym_tools_indent"},{name:"Outdent",title:"Outdent",css:"wym_tools_outdent"=
},{name:"Undo",title:"Undo",css:"wym_tools_undo"},{name:"Redo",title:"Redo"=
,css:"wym_tools_redo"},{name:"CreateLink",title:"Link",css:"wym_tools_link"=
},{name:"Unlink",title:"Unlink",css:"wym_tools_unlink"},{name:"InsertImage"=
,title:"Image",css:"wym_tools_image"},{name:"InsertTable",title:"Table",css=
:"wym_tools_table"},]});var d=3D$.wymeditors(0);var f=3Dfunction(g){show_mo=
dal("Saving page","progress");$.ajax({url:save_url,type:"POST",data:{id:pag=
e_id,content:d.xhtml(),annotations:JSON.stringify(new Object()),_:"true"},s=
uccess:function(){g()}})};$("#save-button").click(function(){f(function(){h=
ide_modal()})});$("#close-button").click(function(){var h=3Dfalse;if(h){var=
g=3Dfunction(){window.onbeforeunload=3Dundefined;window.document.location=
=3Dpage_list_url};show_modal("Close editor","There are unsaved changes to y=
our page which will be lost.",{Cancel:hide_modal,"Save Changes":function(){=
f(g)}},{"Don't Save":g})}else{window.document.location=3Dpage_list_url}});v=
ar a=3D$("<div class=3D'galaxy-page-editor-button'><a id=3D'insert-galaxy-l=
ink' class=3D'action-button popup' href=3D'#'>Paragraph type</a></div>");$(=
".wym_area_top").append(a);var b=3D{};$.each(d._options.containersItems,fun=
ction(h,g){var i=3Dg.name;b[g.title.replace("_"," ")]=3Dfunction(){d.contai=
ner(i)}});make_popupmenu(a,b);var c=3D$("<div><a id=3D'insert-galaxy-link' =
class=3D'action-button popup' href=3D'#'>Insert Link to Galaxy Object</a></=
div>").addClass("galaxy-page-editor-button");$(".wym_area_top").append(c);m=
ake_popupmenu(c,{"Insert History Link":function(){d.dialog(Galaxy.DIALOG_HI=
STORY_LINK)},"Insert Dataset Link":function(){d.dialog(Galaxy.DIALOG_DATASE=
T_LINK)},"Insert Workflow Link":function(){d.dialog(Galaxy.DIALOG_WORKFLOW_=
LINK)},"Insert Page Link":function(){d.dialog(Galaxy.DIALOG_PAGE_LINK)},"In=
sert Visualization Link":function(){d.dialog(Galaxy.DIALOG_VISUALIZATION_LI=
NK)},});var e=3D$("<div><a id=3D'embed-galaxy-object' class=3D'action-butto=
n popup' href=3D'#'>Embed Galaxy Object</a></div>").addClass("galaxy-page-e=
ditor-button");$(".wym_area_top").append(e);make_popupmenu(e,{"Embed Histor=
y":function(){d.dialog(Galaxy.DIALOG_EMBED_HISTORY)},"Embed Dataset":functi=
on(){d.dialog(Galaxy.DIALOG_EMBED_DATASET)},"Embed Workflow":function(){d.d=
ialog(Galaxy.DIALOG_EMBED_WORKFLOW)},"Embed Visualization":function(){d.dia=
log(Galaxy.DIALOG_EMBED_VISUALIZATION)},})});
\ No newline at end of file
+var Galaxy=3D{ITEM_HISTORY:"item_history",ITEM_DATASET:"item_dataset",ITEM=
_WORKFLOW:"item_workflow",ITEM_PAGE:"item_page",ITEM_VISUALIZATION:"item_vi=
sualization",DIALOG_HISTORY_LINK:"link_history",DIALOG_DATASET_LINK:"link_d=
ataset",DIALOG_WORKFLOW_LINK:"link_workflow",DIALOG_PAGE_LINK:"link_page",D=
IALOG_VISUALIZATION_LINK:"link_visualization",DIALOG_EMBED_HISTORY:"embed_h=
istory",DIALOG_EMBED_DATASET:"embed_dataset",DIALOG_EMBED_WORKFLOW:"embed_w=
orkflow",DIALOG_EMBED_PAGE:"embed_page",DIALOG_EMBED_VISUALIZATION:"embed_v=
isualization",DIALOG_HISTORY_ANNOTATE:"history_annotate",};function init_ga=
laxy_elts(a){$(".annotation",a._doc.body).each(function(){$(this).click(fun=
ction(){var b=3Da._doc.createRange();b.selectNodeContents(this);var d=3Dwin=
dow.getSelection();d.removeAllRanges();d.addRange(b);var c=3D""})})}functio=
n get_item_info(d){var f,c,b;switch(d){case (Galaxy.ITEM_HISTORY):f=3D"Hist=
ory";c=3D"Histories";b=3D"history";item_class=3D"History";break;case (Galax=
y.ITEM_DATASET):f=3D"Dataset";c=3D"Datasets";b=3D"dataset";item_class=3D"Hi=
storyDatasetAssociation";break;case (Galaxy.ITEM_WORKFLOW):f=3D"Workflow";c=
=3D"Workflows";b=3D"workflow";item_class=3D"StoredWorkflow";break;case (Gal=
axy.ITEM_PAGE):f=3D"Page";c=3D"Pages";b=3D"page";item_class=3D"Page";break;=
case (Galaxy.ITEM_VISUALIZATION):f=3D"Visualization";c=3D"Visualizations";b=
=3D"visualization";item_class=3D"Visualization";break}var e=3D"list_"+c.toL=
owerCase()+"_for_selection";var a=3Dlist_objects_url.replace("LIST_ACTION",=
e);return{singular:f,plural:c,controller:b,iclass:item_class,list_ajax_url:=
a}}function make_item_importable(a,c,b){ajax_url=3Dset_accessible_url.repla=
ce("ITEM_CONTROLLER",a);$.ajax({type:"POST",url:ajax_url,data:{id:c,accessi=
ble:"True"},error:function(){alert("Making "+b+" accessible failed")}})}WYM=
editor.editor.prototype.dialog=3Dfunction(i,e,g){var a=3Dthis;var b=3Da.uni=
queStamp();var f=3Da.selected();function h(){$("#set_link_id").click(functi=
on(){$("#link_attribute_label").text("ID/Name");var k=3D$(".wym_href");k.ad=
dClass("wym_id").removeClass("wym_href");if(f){k.val($(f).attr("id"))}$(thi=
s).remove()})}if(i=3D=3DWYMeditor.DIALOG_LINK){if(f){$(a._options.hrefSelec=
tor).val($(f).attr(WYMeditor.HREF));$(a._options.srcSelector).val($(f).attr=
(WYMeditor.SRC));$(a._options.titleSelector).val($(f).attr(WYMeditor.TITLE)=
);$(a._options.altSelector).val($(f).attr(WYMeditor.ALT))}var c,d;if(f){c=
=3D$(f).attr("href");if(c=3D=3Dundefined){c=3D""}d=3D$(f).attr("title");if(=
d=3D=3Dundefined){d=3D""}}show_modal("Create Link","<div><div><label id=3D'=
link_attribute_label'>URL <span style=3D'float: right; font-size: 90%'><a h=
ref=3D'#' id=3D'set_link_id'>Create in-page anchor</a></span></label><br><i=
nput type=3D'text' class=3D'wym_href' value=3D'"+c+"' size=3D'40' /></div><=
div><label>Title</label><br><input type=3D'text' class=3D'wym_title' value=
=3D'"+d+"' size=3D'40' /></div><div>",{"Make link":function(){var m=3D$(a._=
options.hrefSelector).val()||"",k=3D$(".wym_id").val()||"",n=3D$(a._options=
.titleSelector).val()||"";if(m||k){a._exec(WYMeditor.CREATE_LINK,b);var l=
=3D$("a[href=3D"+b+"]",a._doc.body);l.attr(WYMeditor.HREF,m).attr(WYMeditor=
.TITLE,n).attr("id",k);if(l.text().indexOf("wym-")=3D=3D=3D0){l.text(n)}}hi=
de_modal()},Cancel:function(){hide_modal()}},{},h)}if(i=3D=3DWYMeditor.DIAL=
OG_IMAGE){if(a._selected_image){$(a._options.dialogImageSelector+" "+a._opt=
ions.srcSelector).val($(a._selected_image).attr(WYMeditor.SRC));$(a._option=
s.dialogImageSelector+" "+a._options.titleSelector).val($(a._selected_image=
).attr(WYMeditor.TITLE));$(a._options.dialogImageSelector+" "+a._options.al=
tSelector).val($(a._selected_image).attr(WYMeditor.ALT))}show_modal("Image"=
,"<div class=3D'row'><label>URL</label><br><input type=3D'text' class=3D'wy=
m_src' value=3D'' size=3D'40' /></div><div class=3D'row'><label>Alt text</l=
abel><br><input type=3D'text' class=3D'wym_alt' value=3D'' size=3D'40' /></=
div><div class=3D'row'><label>Title</label><br><input type=3D'text' class=
=3D'wym_title' value=3D'' size=3D'40' /></div>",{Insert:function(){var k=3D=
$(a._options.srcSelector).val();if(k.length>0){a._exec(WYMeditor.INSERT_IMA=
GE,b);$("img[src$=3D"+b+"]",a._doc.body).attr(WYMeditor.SRC,k).attr(WYMedit=
or.TITLE,$(a._options.titleSelector).val()).attr(WYMeditor.ALT,$(a._options=
.altSelector).val())}hide_modal()},Cancel:function(){hide_modal()}});return=
}if(i=3D=3DWYMeditor.DIALOG_TABLE){show_modal("Table","<div class=3D'row'><=
label>Caption</label><br><input type=3D'text' class=3D'wym_caption' value=
=3D'' size=3D'40' /></div><div class=3D'row'><label>Summary</label><br><inp=
ut type=3D'text' class=3D'wym_summary' value=3D'' size=3D'40' /></div><div =
class=3D'row'><label>Number Of Rows<br></label><input type=3D'text' class=
=3D'wym_rows' value=3D'3' size=3D'3' /></div><div class=3D'row'><label>Numb=
er Of Cols<br></label><input type=3D'text' class=3D'wym_cols' value=3D'2' s=
ize=3D'3' /></div>",{Insert:function(){var o=3D$(a._options.rowsSelector).v=
al();var r=3D$(a._options.colsSelector).val();if(o>0&&r>0){var n=3Da._doc.c=
reateElement(WYMeditor.TABLE);var l=3Dnull;var q=3Dnull;var k=3D$(a._option=
s.captionSelector).val();var p=3Dn.createCaption();p.innerHTML=3Dk;for(x=3D=
0;x<o;x++){l=3Dn.insertRow(x);for(y=3D0;y<r;y++){l.insertCell(y)}}$(n).attr=
("summary",$(a._options.summarySelector).val());var m=3D$(a.findUp(a.contai=
ner(),WYMeditor.MAIN_CONTAINERS)).get(0);if(!m||!m.parentNode){$(a._doc.bod=
y).append(n)}else{$(m).after(n)}}hide_modal()},Cancel:function(){hide_modal=
()}})}if(i=3D=3DGalaxy.DIALOG_HISTORY_LINK||i=3D=3DGalaxy.DIALOG_DATASET_LI=
NK||i=3D=3DGalaxy.DIALOG_WORKFLOW_LINK||i=3D=3DGalaxy.DIALOG_PAGE_LINK||i=
=3D=3DGalaxy.DIALOG_VISUALIZATION_LINK){var j;switch(i){case (Galaxy.DIALOG=
_HISTORY_LINK):j=3Dget_item_info(Galaxy.ITEM_HISTORY);break;case (Galaxy.DI=
ALOG_DATASET_LINK):j=3Dget_item_info(Galaxy.ITEM_DATASET);break;case (Galax=
y.DIALOG_WORKFLOW_LINK):j=3Dget_item_info(Galaxy.ITEM_WORKFLOW);break;case =
(Galaxy.DIALOG_PAGE_LINK):j=3Dget_item_info(Galaxy.ITEM_PAGE);break;case (G=
alaxy.DIALOG_VISUALIZATION_LINK):j=3Dget_item_info(Galaxy.ITEM_VISUALIZATIO=
N);break}$.ajax({url:j.list_ajax_url,data:{},error:function(){alert("Failed=
to list "+j.plural.toLowerCase()+" for selection")},success:function(k){sh=
ow_modal("Insert Link to "+j.singular,k+"<div><input id=3D'make-importable'=
type=3D'checkbox' checked/>Make the selected "+j.plural.toLowerCase()+" ac=
cessible so that they can viewed by everyone.</div>",{Insert:function(){var=
m=3Dfalse;if($("#make-importable:checked").val()!=3D=3Dnull){m=3Dtrue}var =
l=3Dnew Array();$("input[name=3Did]:checked").each(function(){var n=3D$(thi=
s).val();if(m){make_item_importable(j.controller,n,j.singular)}url_template=
=3Dget_name_and_link_url+n;ajax_url=3Durl_template.replace("ITEM_CONTROLLER=
",j.controller);$.getJSON(ajax_url,function(p){a._exec(WYMeditor.CREATE_LIN=
K,b);var o=3D$("a[href=3D"+b+"]",a._doc.body).text();if(o=3D=3D""||o=3D=3Db=
){a.insert("<a href=3D'"+p.link+"'>"+j.singular+" '"+p.name+"'</a>")}else{$=
("a[href=3D"+b+"]",a._doc.body).attr(WYMeditor.HREF,p.link).attr(WYMeditor.=
TITLE,j.singular+n)}})});hide_modal()},Cancel:function(){hide_modal()}})}})=
}if(i=3D=3DGalaxy.DIALOG_EMBED_HISTORY||i=3D=3DGalaxy.DIALOG_EMBED_DATASET|=
|i=3D=3DGalaxy.DIALOG_EMBED_WORKFLOW||i=3D=3DGalaxy.DIALOG_EMBED_PAGE||i=3D=
=3DGalaxy.DIALOG_EMBED_VISUALIZATION){var j;switch(i){case (Galaxy.DIALOG_E=
MBED_HISTORY):j=3Dget_item_info(Galaxy.ITEM_HISTORY);break;case (Galaxy.DIA=
LOG_EMBED_DATASET):j=3Dget_item_info(Galaxy.ITEM_DATASET);break;case (Galax=
y.DIALOG_EMBED_WORKFLOW):j=3Dget_item_info(Galaxy.ITEM_WORKFLOW);break;case=
(Galaxy.DIALOG_EMBED_PAGE):j=3Dget_item_info(Galaxy.ITEM_PAGE);break;case =
(Galaxy.DIALOG_EMBED_VISUALIZATION):j=3Dget_item_info(Galaxy.ITEM_VISUALIZA=
TION);break}$.ajax({url:j.list_ajax_url,data:{},error:function(){alert("Fai=
led to list "+j.plural.toLowerCase()+" for selection")},success:function(k)=
{if(i=3D=3DGalaxy.DIALOG_EMBED_HISTORY||i=3D=3DGalaxy.DIALOG_EMBED_WORKFLOW=
||i=3D=3DGalaxy.DIALOG_EMBED_VISUALIZATION){k=3Dk+"<div><input id=3D'make-i=
mportable' type=3D'checkbox' checked/>Make the selected "+j.plural.toLowerC=
ase()+" accessible so that they can viewed by everyone.</div>"}show_modal("=
Embed "+j.plural,k,{Embed:function(){var l=3Dfalse;if($("#make-importable:c=
hecked").val()!=3Dnull){l=3Dtrue}$("input[name=3Did]:checked").each(functio=
n(){var m=3D$(this).val();var p=3D$("label[for=3D'"+m+"']:first").text();if=
(l){make_item_importable(j.controller,m,j.singular)}var n=3Dj.iclass+"-"+m;=
var o=3D"<p><div id=3D'"+n+"' class=3D'embedded-item "+j.singular.toLowerCa=
se()+" placeholder'><p class=3D'title'>Embedded Galaxy "+j.singular+" '"+p+=
"'</p><p class=3D'content'> [Do=
not edit this block; Galaxy will fill it in with the annotated "+j.singula=
r.toLowerCase()+" when it is displayed.] =
</p></div></p>";a.insert(" ");a.insert(o);$("#"+n,a._doc.body).e=
ach(function(){var q=3Dtrue;while(q){var r=3D$(this).prev();if(r.length!=3D=
0&&jQuery.trim(r.text())=3D=3D""){r.remove()}else{q=3Dfalse}}})});hide_moda=
l()},Cancel:function(){hide_modal()}})}})}if(i=3D=3DGalaxy.DIALOG_ANNOTATE_=
HISTORY){$.ajax({url:list_histories_for_selection_url,data:{},error:functio=
n(){alert("Grid refresh failed")},success:function(k){show_modal("Insert Li=
nk to History",k,{Annotate:function(){var l=3Dnew Array();$("input[name=3Di=
d]:checked").each(function(){var m=3D$(this).val();$.ajax({url:get_history_=
annotation_table_url,data:{id:m},error:function(){alert("Grid refresh faile=
d")},success:function(n){a.insert(n);init_galaxy_elts(a)}})});hide_modal()}=
,Cancel:function(){hide_modal()}})}})}};$(function(){$(document).ajaxError(=
function(i,g){var h=3Dg.responseText||g.statusText||"Could not connect to s=
erver";show_modal("Server error",h,{"Ignore error":hide_modal});return fals=
e});$("[name=3Dpage_content]").wymeditor({skin:"galaxy",basePath:editor_bas=
e_path,iframeBasePath:iframe_base_path,boxHtml:"<table class=3D'wym_box' wi=
dth=3D'100%' height=3D'100%'><tr><td><div class=3D'wym_area_top'>"+WYMedito=
r.TOOLS+"</div></td></tr><tr height=3D'100%'><td><div class=3D'wym_area_mai=
n' style=3D'height: 100%;'>"+WYMeditor.IFRAME+WYMeditor.STATUS+"</div></div=
></td></tr></table>",toolsItems:[{name:"Bold",title:"Strong",css:"wym_tools=
_strong"},{name:"Italic",title:"Emphasis",css:"wym_tools_emphasis"},{name:"=
Superscript",title:"Superscript",css:"wym_tools_superscript"},{name:"Subscr=
ipt",title:"Subscript",css:"wym_tools_subscript"},{name:"InsertOrderedList"=
,title:"Ordered_List",css:"wym_tools_ordered_list"},{name:"InsertUnorderedL=
ist",title:"Unordered_List",css:"wym_tools_unordered_list"},{name:"Indent",=
title:"Indent",css:"wym_tools_indent"},{name:"Outdent",title:"Outdent",css:=
"wym_tools_outdent"},{name:"Undo",title:"Undo",css:"wym_tools_undo"},{name:=
"Redo",title:"Redo",css:"wym_tools_redo"},{name:"CreateLink",title:"Link",c=
ss:"wym_tools_link"},{name:"Unlink",title:"Unlink",css:"wym_tools_unlink"},=
{name:"InsertImage",title:"Image",css:"wym_tools_image"},{name:"InsertTable=
",title:"Table",css:"wym_tools_table"},]});var d=3D$.wymeditors(0);var f=3D=
function(g){show_modal("Saving page","progress");$.ajax({url:save_url,type:=
"POST",data:{id:page_id,content:d.xhtml(),annotations:JSON.stringify(new Ob=
ject()),_:"true"},success:function(){g()}})};$("#save-button").click(functi=
on(){f(function(){hide_modal()})});$("#close-button").click(function(){var =
h=3Dfalse;if(h){var g=3Dfunction(){window.onbeforeunload=3Dundefined;window=
.document.location=3Dpage_list_url};show_modal("Close editor","There are un=
saved changes to your page which will be lost.",{Cancel:hide_modal,"Save Ch=
anges":function(){f(g)}},{"Don't Save":g})}else{window.document.location=3D=
page_list_url}});var a=3D$("<div class=3D'galaxy-page-editor-button'><a id=
=3D'insert-galaxy-link' class=3D'action-button popup' href=3D'#'>Paragraph =
type</a></div>");$(".wym_area_top").append(a);var b=3D{};$.each(d._options.=
containersItems,function(h,g){var i=3Dg.name;b[g.title.replace("_"," ")]=3D=
function(){d.container(i)}});make_popupmenu(a,b);var c=3D$("<div><a id=3D'i=
nsert-galaxy-link' class=3D'action-button popup' href=3D'#'>Insert Link to =
Galaxy Object</a></div>").addClass("galaxy-page-editor-button");$(".wym_are=
a_top").append(c);make_popupmenu(c,{"Insert History Link":function(){d.dial=
og(Galaxy.DIALOG_HISTORY_LINK)},"Insert Dataset Link":function(){d.dialog(G=
alaxy.DIALOG_DATASET_LINK)},"Insert Workflow Link":function(){d.dialog(Gala=
xy.DIALOG_WORKFLOW_LINK)},"Insert Page Link":function(){d.dialog(Galaxy.DIA=
LOG_PAGE_LINK)},"Insert Visualization Link":function(){d.dialog(Galaxy.DIAL=
OG_VISUALIZATION_LINK)},});var e=3D$("<div><a id=3D'embed-galaxy-object' cl=
ass=3D'action-button popup' href=3D'#'>Embed Galaxy Object</a></div>").addC=
lass("galaxy-page-editor-button");$(".wym_area_top").append(e);make_popupme=
nu(e,{"Embed History":function(){d.dialog(Galaxy.DIALOG_EMBED_HISTORY)},"Em=
bed Dataset":function(){d.dialog(Galaxy.DIALOG_EMBED_DATASET)},"Embed Workf=
low":function(){d.dialog(Galaxy.DIALOG_EMBED_WORKFLOW)},"Embed Visualizatio=
n":function(){d.dialog(Galaxy.DIALOG_EMBED_VISUALIZATION)},})});
\ No newline at end of file
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c static/scripts/packed/mvc/tools.js
--- a/static/scripts/packed/mvc/tools.js
+++ b/static/scripts/packed/mvc/tools.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","viz/trackster/util","mvc/data","libs/backbone/b=
ackbone-relational"],function(q,a,r){var f=3DBackbone.RelationalModel.exten=
d({defaults:{name:null,hidden:false},show:function(){this.set("hidden",fals=
e)},hide:function(){this.set("hidden",true)},is_visible:function(){return !=
this.attributes.hidden}});var k=3DBackbone.RelationalModel.extend({defaults=
:{name:null,label:null,type:null,value:null,num_samples:5},initialize:funct=
ion(){this.attributes.html=3Dunescape(this.attributes.html)},copy:function(=
){return new k(this.toJSON())},get_samples:function(){var u=3Dthis.get("typ=
e"),t=3Dnull;if(u=3D=3D=3D"number"){t=3Dd3.scale.linear().domain([this.get(=
"min"),this.get("max")]).ticks(this.get("num_samples"))}else{if(u=3D=3D=3D"=
select"){t=3Dq.map(this.get("options"),function(v){return v[0]})}}return t}=
});var e=3Df.extend({defaults:{description:null,target:null,inputs:[]},rela=
tions:[{type:Backbone.HasMany,key:"inputs",relatedModel:k,reverseRelation:{=
key:"tool",includeInJSON:false}}],urlRoot:galaxy_paths.get("tool_url"),copy=
:function(u){var v=3Dnew e(this.toJSON());if(u){var t=3Dnew Backbone.Collec=
tion();v.get("inputs").each(function(w){if(w.get_samples()){t.push(w)}});v.=
set("inputs",t)}return v},apply_search_results:function(t){(q.indexOf(t,thi=
s.attributes.id)!=3D=3D-1?this.show():this.hide());return this.is_visible()=
},set_input_value:function(t,u){this.get("inputs").find(function(v){return =
v.get("name")=3D=3D=3Dt}).set("value",u)},set_input_values:function(u){var =
t=3Dthis;q.each(q.keys(u),function(v){t.set_input_value(v,u[v])})},run:func=
tion(){return this._run()},rerun:function(u,t){return this._run({action:"re=
run",target_dataset_id:u.id,regions:t})},get_inputs_dict:function(){var t=
=3D{};this.get("inputs").each(function(u){t[u.get("name")]=3Du.get("value")=
});return t},_run:function(v){var w=3Dq.extend({tool_id:this.id,inputs:this=
.get_inputs_dict()},v);var u=3D$.Deferred(),t=3Dnew a.ServerStateDeferred({=
ajax_settings:{url:this.urlRoot,data:JSON.stringify(w),dataType:"json",cont=
entType:"application/json",type:"POST"},interval:2000,success_fn:function(x=
){return x!=3D=3D"pending"}});$.when(t.go()).then(function(x){u.resolve(new=
r.DatasetCollection().reset(x))});return u}});var i=3DBackbone.Collection.=
extend({model:e});var m=3Df.extend({});var p=3Df.extend({defaults:{elems:[]=
,open:false},clear_search_results:function(){q.each(this.attributes.elems,f=
unction(t){t.show()});this.show();this.set("open",false)},apply_search_resu=
lts:function(u){var v=3Dtrue,t;q.each(this.attributes.elems,function(w){if(=
w instanceof m){t=3Dw;t.hide()}else{if(w instanceof e){if(w.apply_search_re=
sults(u)){v=3Dfalse;if(t){t.show()}}}}});if(v){this.hide()}else{this.show()=
;this.set("open",true)}}});var b=3Df.extend({defaults:{search_hint_string:"=
search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search=
_url:"",visible:true,query:"",results:null,clear_key:27},initialize:functio=
n(){this.on("change:query",this.do_search)},do_search:function(){var v=3Dth=
is.attributes.query;if(v.length<this.attributes.min_chars_for_search){this.=
set("results",null);return}var u=3Dv+"*";if(this.timer){clearTimeout(this.t=
imer)}$("#search-clear-btn").hide();$("#search-spinner").show();var t=3Dthi=
s;this.timer=3DsetTimeout(function(){$.get(t.attributes.search_url,{query:u=
},function(w){t.set("results",w);$("#search-spinner").hide();$("#search-cle=
ar-btn").show()},"json")},200)},clear_search:function(){this.set("query",""=
);this.set("results",null)}});var j=3DBackbone.Collection.extend({url:"/too=
ls",tools:new i(),parse:function(t){var u=3Dfunction(x){var w=3Dx.type;if(w=
=3D=3D=3D"tool"){return new e(x)}else{if(w=3D=3D=3D"section"){var v=3Dq.map=
(x.elems,u);x.elems=3Dv;return new p(x)}else{if(w=3D=3D=3D"label"){return n=
ew m(x)}}}};return q.map(t,u)},initialize:function(t){this.tool_search=3Dt.=
tool_search;this.tool_search.on("change:results",this.apply_search_results,=
this);this.on("reset",this.populate_tools,this)},populate_tools:function(){=
var t=3Dthis;t.tools=3Dnew i();this.each(function(u){if(u instanceof p){q.e=
ach(u.attributes.elems,function(v){if(v instanceof e){t.tools.push(v)}})}el=
se{if(u instanceof e){t.tools.push(u)}}})},clear_search_results:function(){=
this.each(function(t){if(t instanceof p){t.clear_search_results()}else{t.sh=
ow()}})},apply_search_results:function(){var u=3Dthis.tool_search.attribute=
s.results;if(u=3D=3D=3Dnull){this.clear_search_results();return}var t=3Dnul=
l;this.each(function(v){if(v instanceof m){t=3Dv;t.hide()}else{if(v instanc=
eof e){if(v.apply_search_results(u)){if(t){t.show()}}}else{t=3Dnull;v.apply=
_search_results(u)}}})}});var n=3DBackbone.View.extend({initialize:function=
(){this.model.on("change:hidden",this.update_visible,this);this.update_visi=
ble()},update_visible:function(){(this.model.attributes.hidden?this.$el.hid=
e():this.$el.show())}});var h=3Dn.extend({tagName:"div",template:Handlebars=
.templates.tool_link,render:function(){this.$el.append(this.template(this.m=
odel.toJSON()));return this}});var c=3Dn.extend({tagName:"div",className:"t=
oolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.mod=
el.attributes.name));return this}});var g=3Dn.extend({tagName:"div",classNa=
me:"toolSectionWrapper",template:Handlebars.templates.panel_section,initial=
ize:function(){n.prototype.initialize.call(this);this.model.on("change:open=
",this.update_open,this)},render:function(){this.$el.append(this.template(t=
his.model.toJSON()));var t=3Dthis.$el.find(".toolSectionBody");q.each(this.=
model.attributes.elems,function(u){if(u instanceof e){var v=3Dnew h({model:=
u,className:"toolTitle"});v.render();t.append(v.$el)}else{if(u instanceof m=
){var w=3Dnew c({model:u});w.render();t.append(w.$el)}else{}}});return this=
},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.mo=
del.set("open",!this.model.attributes.open)},update_open:function(){(this.m=
odel.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"=
):this.$el.children(".toolSectionBody").slideUp("fast"))}});var l=3DBackbon=
e.View.extend({tagName:"div",id:"tool-search",className:"bar",template:Hand=
lebars.templates.tool_search,events:{click:"focus_and_select","keyup :input=
":"query_changed","click #search-clear-btn":"clear"},render:function(){this=
.$el.append(this.template(this.model.toJSON()));if(!this.model.is_visible()=
){this.$el.hide()}this.$el.find(".tooltip").tooltip();return this},focus_an=
d_select:function(){this.$el.find(":input").focus().select()},clear:functio=
n(){this.model.clear_search();this.$el.find(":input").val(this.model.attrib=
utes.search_hint_string);this.focus_and_select();return false},query_change=
d:function(t){if((this.model.attributes.clear_key)&&(this.model.attributes.=
clear_key=3D=3D=3Dt.which)){this.clear();return false}this.model.set("query=
",this.$el.find(":input").val())}});var s=3DBackbone.View.extend({tagName:"=
div",className:"toolMenu",initialize:function(){this.collection.tool_search=
.on("change:results",this.handle_search_results,this)},render:function(){va=
r t=3Dthis;var u=3Dnew l({model:this.collection.tool_search});u.render();t.=
$el.append(u.$el);this.collection.each(function(w){if(w instanceof p){var v=
=3Dnew g({model:w});v.render();t.$el.append(v.$el)}else{if(w instanceof e){=
var x=3Dnew h({model:w,className:"toolTitleNoSection"});x.render();t.$el.ap=
pend(x.$el)}else{if(w instanceof m){var y=3Dnew c({model:w});y.render();t.$=
el.append(y.$el)}}}});t.$el.find("a.tool-link").click(function(x){var w=3D$=
(this).attr("class").split(/\s+/)[0],v=3Dt.collection.tools.get(w);t.trigge=
r("tool_link_click",x,v)});return this},handle_search_results:function(){va=
r t=3Dthis.collection.tool_search.attributes.results;if(t&&t.length=3D=3D=
=3D0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}}=
);var o=3DBackbone.View.extend({className:"toolForm",template:Handlebars.te=
mplates.tool_form,render:function(){this.$el.children().remove();this.$el.a=
ppend(this.template(this.model.toJSON()))}});var d=3DBackbone.View.extend({=
className:"toolMenuAndView",initialize:function(){this.tool_panel_view=3Dne=
w s({collection:this.collection});this.tool_form_view=3Dnew o()},render:fun=
ction(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float",=
"left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.h=
ide();this.$el.append(this.tool_form_view.$el);var t=3Dthis;this.tool_panel=
_view.on("tool_link_click",function(v,u){v.preventDefault();t.show_tool(u)}=
)},show_tool:function(u){var t=3Dthis;u.fetch().done(function(){t.tool_form=
_view.model=3Du;t.tool_form_view.render();t.tool_form_view.$el.show();$("#l=
eft").width("650px")})}});return{Tool:e,ToolSearch:b,ToolPanel:j,ToolPanelV=
iew:s,ToolFormView:o}});
\ No newline at end of file
+define(["libs/underscore","viz/trackster/util","mvc/data","libs/backbone/b=
ackbone-relational"],function(q,a,r){var g=3DBackbone.RelationalModel.exten=
d({defaults:{name:null,hidden:false},show:function(){this.set("hidden",fals=
e)},hide:function(){this.set("hidden",true)},is_visible:function(){return !=
this.attributes.hidden}});var c=3DBackbone.RelationalModel.extend({defaults=
:{name:null,label:null,type:null,value:null,num_samples:5},initialize:funct=
ion(){this.attributes.html=3Dunescape(this.attributes.html)},copy:function(=
){return new c(this.toJSON())},get_samples:function(){var u=3Dthis.get("typ=
e"),t=3Dnull;if(u=3D=3D=3D"number"){t=3Dd3.scale.linear().domain([this.get(=
"min"),this.get("max")]).ticks(this.get("num_samples"))}else{if(u=3D=3D=3D"=
select"){t=3Dq.map(this.get("options"),function(v){return v[0]})}}return t}=
});var f=3Dg.extend({defaults:{description:null,target:null,inputs:[]},rela=
tions:[{type:Backbone.HasMany,key:"inputs",relatedModel:c,reverseRelation:{=
key:"tool",includeInJSON:false}}],urlRoot:galaxy_paths.get("tool_url"),copy=
:function(u){var v=3Dnew f(this.toJSON());if(u){var t=3Dnew Backbone.Collec=
tion();v.get("inputs").each(function(w){if(w.get_samples()){t.push(w)}});v.=
set("inputs",t)}return v},apply_search_results:function(t){(q.indexOf(t,thi=
s.attributes.id)!=3D=3D-1?this.show():this.hide());return this.is_visible()=
},set_input_value:function(t,u){this.get("inputs").find(function(v){return =
v.get("name")=3D=3D=3Dt}).set("value",u)},set_input_values:function(u){var =
t=3Dthis;q.each(q.keys(u),function(v){t.set_input_value(v,u[v])})},run:func=
tion(){return this._run()},rerun:function(u,t){return this._run({action:"re=
run",target_dataset_id:u.id,regions:t})},get_inputs_dict:function(){var t=
=3D{};this.get("inputs").each(function(u){t[u.get("name")]=3Du.get("value")=
});return t},_run:function(v){var w=3Dq.extend({tool_id:this.id,inputs:this=
.get_inputs_dict()},v);var u=3D$.Deferred(),t=3Dnew a.ServerStateDeferred({=
ajax_settings:{url:this.urlRoot,data:JSON.stringify(w),dataType:"json",cont=
entType:"application/json",type:"POST"},interval:2000,success_fn:function(x=
){return x!=3D=3D"pending"}});$.when(t.go()).then(function(x){u.resolve(new=
r.DatasetCollection().reset(x))});return u}});var j=3DBackbone.Collection.=
extend({model:f});var m=3Dg.extend({});var p=3Dg.extend({defaults:{elems:[]=
,open:false},clear_search_results:function(){q.each(this.attributes.elems,f=
unction(t){t.show()});this.show();this.set("open",false)},apply_search_resu=
lts:function(u){var v=3Dtrue,t;q.each(this.attributes.elems,function(w){if(=
w instanceof m){t=3Dw;t.hide()}else{if(w instanceof f){if(w.apply_search_re=
sults(u)){v=3Dfalse;if(t){t.show()}}}}});if(v){this.hide()}else{this.show()=
;this.set("open",true)}}});var b=3Dg.extend({defaults:{search_hint_string:"=
search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search=
_url:"",visible:true,query:"",results:null,clear_key:27},initialize:functio=
n(){this.on("change:query",this.do_search)},do_search:function(){var v=3Dth=
is.attributes.query;if(v.length<this.attributes.min_chars_for_search){this.=
set("results",null);return}var u=3Dv+"*";if(this.timer){clearTimeout(this.t=
imer)}$("#search-clear-btn").hide();$("#search-spinner").show();var t=3Dthi=
s;this.timer=3DsetTimeout(function(){$.get(t.attributes.search_url,{query:u=
},function(w){t.set("results",w);$("#search-spinner").hide();$("#search-cle=
ar-btn").show()},"json")},200)},clear_search:function(){this.set("query",""=
);this.set("results",null)}});var k=3DBackbone.Collection.extend({url:"/too=
ls",tools:new j(),parse:function(t){var u=3Dfunction(x){var w=3Dx.type;if(w=
=3D=3D=3D"tool"){return new f(x)}else{if(w=3D=3D=3D"section"){var v=3Dq.map=
(x.elems,u);x.elems=3Dv;return new p(x)}else{if(w=3D=3D=3D"label"){return n=
ew m(x)}}}};return q.map(t,u)},initialize:function(t){this.tool_search=3Dt.=
tool_search;this.tool_search.on("change:results",this.apply_search_results,=
this);this.on("reset",this.populate_tools,this)},populate_tools:function(){=
var t=3Dthis;t.tools=3Dnew j();this.each(function(u){if(u instanceof p){q.e=
ach(u.attributes.elems,function(v){if(v instanceof f){t.tools.push(v)}})}el=
se{if(u instanceof f){t.tools.push(u)}}})},clear_search_results:function(){=
this.each(function(t){if(t instanceof p){t.clear_search_results()}else{t.sh=
ow()}})},apply_search_results:function(){var u=3Dthis.tool_search.attribute=
s.results;if(u=3D=3D=3Dnull){this.clear_search_results();return}var t=3Dnul=
l;this.each(function(v){if(v instanceof m){t=3Dv;t.hide()}else{if(v instanc=
eof f){if(v.apply_search_results(u)){if(t){t.show()}}}else{t=3Dnull;v.apply=
_search_results(u)}}})}});var n=3DBackbone.View.extend({initialize:function=
(){this.model.on("change:hidden",this.update_visible,this);this.update_visi=
ble()},update_visible:function(){(this.model.attributes.hidden?this.$el.hid=
e():this.$el.show())}});var i=3Dn.extend({tagName:"div",template:Handlebars=
.templates.tool_link,render:function(){this.$el.append(this.template(this.m=
odel.toJSON()));return this}});var d=3Dn.extend({tagName:"div",className:"t=
oolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.mod=
el.attributes.name));return this}});var h=3Dn.extend({tagName:"div",classNa=
me:"toolSectionWrapper",template:Handlebars.templates.panel_section,initial=
ize:function(){n.prototype.initialize.call(this);this.model.on("change:open=
",this.update_open,this)},render:function(){this.$el.append(this.template(t=
his.model.toJSON()));var t=3Dthis.$el.find(".toolSectionBody");q.each(this.=
model.attributes.elems,function(u){if(u instanceof f){var v=3Dnew i({model:=
u,className:"toolTitle"});v.render();t.append(v.$el)}else{if(u instanceof m=
){var w=3Dnew d({model:u});w.render();t.append(w.$el)}else{}}});return this=
},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.mo=
del.set("open",!this.model.attributes.open)},update_open:function(){(this.m=
odel.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"=
):this.$el.children(".toolSectionBody").slideUp("fast"))}});var l=3DBackbon=
e.View.extend({tagName:"div",id:"tool-search",className:"bar",template:Hand=
lebars.templates.tool_search,events:{click:"focus_and_select","keyup :input=
":"query_changed","click #search-clear-btn":"clear"},render:function(){this=
.$el.append(this.template(this.model.toJSON()));if(!this.model.is_visible()=
){this.$el.hide()}this.$el.find(".tooltip").tooltip();return this},focus_an=
d_select:function(){this.$el.find(":input").focus().select()},clear:functio=
n(){this.model.clear_search();this.$el.find(":input").val(this.model.attrib=
utes.search_hint_string);this.focus_and_select();return false},query_change=
d:function(t){if((this.model.attributes.clear_key)&&(this.model.attributes.=
clear_key=3D=3D=3Dt.which)){this.clear();return false}this.model.set("query=
",this.$el.find(":input").val())}});var s=3DBackbone.View.extend({tagName:"=
div",className:"toolMenu",initialize:function(){this.collection.tool_search=
.on("change:results",this.handle_search_results,this)},render:function(){va=
r t=3Dthis;var u=3Dnew l({model:this.collection.tool_search});u.render();t.=
$el.append(u.$el);this.collection.each(function(w){if(w instanceof p){var v=
=3Dnew h({model:w});v.render();t.$el.append(v.$el)}else{if(w instanceof f){=
var x=3Dnew i({model:w,className:"toolTitleNoSection"});x.render();t.$el.ap=
pend(x.$el)}else{if(w instanceof m){var y=3Dnew d({model:w});y.render();t.$=
el.append(y.$el)}}}});t.$el.find("a.tool-link").click(function(x){var w=3D$=
(this).attr("class").split(/\s+/)[0],v=3Dt.collection.tools.get(w);t.trigge=
r("tool_link_click",x,v)});return this},handle_search_results:function(){va=
r t=3Dthis.collection.tool_search.attributes.results;if(t&&t.length=3D=3D=
=3D0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}}=
);var o=3DBackbone.View.extend({className:"toolForm",template:Handlebars.te=
mplates.tool_form,render:function(){this.$el.children().remove();this.$el.a=
ppend(this.template(this.model.toJSON()))}});var e=3DBackbone.View.extend({=
className:"toolMenuAndView",initialize:function(){this.tool_panel_view=3Dne=
w s({collection:this.collection});this.tool_form_view=3Dnew o()},render:fun=
ction(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float",=
"left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.h=
ide();this.$el.append(this.tool_form_view.$el);var t=3Dthis;this.tool_panel=
_view.on("tool_link_click",function(v,u){v.preventDefault();t.show_tool(u)}=
)},show_tool:function(u){var t=3Dthis;u.fetch().done(function(){t.tool_form=
_view.model=3Du;t.tool_form_view.render();t.tool_form_view.$el.show();$("#l=
eft").width("650px")})}});return{Tool:f,ToolSearch:b,ToolPanel:k,ToolPanelV=
iew:s,ToolFormView:o}});
\ No newline at end of file
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c templates/webapps/tool_shed/repository/tool_form.mako
--- a/templates/webapps/tool_shed/repository/tool_form.mako
+++ b/templates/webapps/tool_shed/repository/tool_form.mako
@@ -70,6 +70,8 @@
=20
<%def name=3D"row_for_param( prefix, param, parent_state, other_va=
lues )"><%
+ # Disable refresh_on_change for select lists displayed in =
the tool shed.=20
+ param.refresh_on_change =3D False
label =3D param.get_label()
if isinstance( param, DataToolParameter ) or isinstance( p=
aram, ColumnListParameter ) or isinstance( param, GenomeBuildParameter ):
field =3D SelectField( param.name )
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c test/install_and_test_tool_shed_repositories/functional_t=
ests.py
--- a/test/install_and_test_tool_shed_repositories/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/functional_tests.py
@@ -6,6 +6,7 @@
=20
import os, sys, shutil, tempfile, re, string, urllib, platform
from time import strftime
+from ConfigParser import SafeConfigParser
=20
# Assume we are run from the galaxy root directory, add lib to the python =
path
cwd =3D os.getcwd()
@@ -73,6 +74,40 @@
default_galaxy_test_port_max =3D 10999
default_galaxy_test_host =3D '127.0.0.1'
=20
+# should this serve static resources (scripts, images, styles, etc.)
+STATIC_ENABLED =3D True
+
+def get_static_settings():
+ """Returns dictionary of the settings necessary for a galaxy App
+ to be wrapped in the static middleware.
+
+ This mainly consists of the filesystem locations of url-mapped
+ static resources.
+ """
+ cwd =3D os.getcwd()
+ static_dir =3D os.path.join( cwd, 'static' )
+ #TODO: these should be copied from universe_wsgi.ini
+ return dict(
+ #TODO: static_enabled needed here?
+ static_enabled =3D True,
+ static_cache_time =3D 360,
+ static_dir =3D static_dir,
+ static_images_dir =3D os.path.join( static_dir, 'images', '' ),
+ static_favicon_dir =3D os.path.join( static_dir, 'favicon.ico' ),
+ static_scripts_dir =3D os.path.join( static_dir, 'scripts', '' ),
+ static_style_dir =3D os.path.join( static_dir, 'june_2007_style=
', 'blue' ),
+ static_robots_txt =3D os.path.join( static_dir, 'robots.txt' ),
+ )
+
+def get_webapp_global_conf():
+ """Get the global_conf dictionary sent as the first argument to app_fa=
ctory.
+ """
+ # (was originally sent 'dict()') - nothing here for now except static =
settings
+ global_conf =3D dict()
+ if STATIC_ENABLED:
+ global_conf.update( get_static_settings() )
+ return global_conf
+
# Optionally, set the environment variable GALAXY_INSTALL_TEST_TOOL_SHEDS_=
CONF
# to the location of a tool sheds configuration file that includes the too=
l shed
# that repositories will be installed from.
@@ -219,6 +254,36 @@
success =3D result.wasSuccessful()
return success
=20
+def generate_config_file( input_filename, output_filename, config_items ):
+ '''
+ Generate a config file with the configuration that has been defined fo=
r the embedded web application.
+ This is mostly relevant when setting metadata externally, since the sc=
ript for doing that does not
+ have access to app.config.
+ '''=20
+ cp =3D SafeConfigParser()
+ cp.read( input_filename )
+ config_items_by_section =3D []
+ for label, value in config_items:
+ found =3D False
+ # Attempt to determine the correct section for this configuration =
option.
+ for section in cp.sections():
+ if cp.has_option( section, label ):
+ config_tuple =3D section, label, value
+ config_items_by_section.append( config_tuple )
+ found =3D True
+ continue
+ # Default to app:main if no section was found.
+ if not found:
+ config_tuple =3D 'app:main', label, value
+ config_items_by_section.append( config_tuple )
+ # Replace the default values with the provided configuration.
+ for section, label, value in config_items_by_section:
+ cp.remove_option( section, label )
+ cp.set( section, label, str( value ) )
+ fh =3D open( output_filename, 'w' )
+ cp.write( fh )
+ fh.close()
+
def get_api_url( base, parts=3D[], params=3DNone, key=3DNone ):
if 'api' in parts and parts.index( 'api' ) !=3D 0:
parts.pop( parts.index( 'api' ) )
@@ -554,48 +619,64 @@
# Generate the migrated_tool_conf.xml file.
migrated_tool_conf_xml =3D tool_conf_template_parser.safe_substitute( =
shed_tool_path=3Dgalaxy_migrated_tool_path )
file( galaxy_migrated_tool_conf_file, 'w' ).write( migrated_tool_conf_=
xml )
-
+ # Write the embedded web application's specific configuration to a tem=
porary file. This is necessary in order for
+ # the external metadata script to find the right datasets.
+ kwargs =3D dict( admin_users =3D 'test(a)bx.psu.edu',
+ allow_user_creation =3D True,
+ allow_user_deletion =3D True,
+ allow_library_path_paste =3D True,
+ database_connection =3D database_connection,
+ datatype_converters_config_file =3D "datatype_converter=
s_conf.xml.sample",
+ file_path =3D galaxy_file_path,
+ id_secret =3D galaxy_encode_secret,
+ job_queue_workers =3D 5,
+ log_destination =3D "stdout",
+ migrated_tools_config =3D galaxy_migrated_tool_conf_fil=
e,
+ new_file_path =3D galaxy_tempfiles,
+ running_functional_tests =3D True,
+ shed_tool_data_table_config =3D shed_tool_data_table_co=
nf_file,
+ shed_tool_path =3D galaxy_shed_tool_path,
+ template_path =3D "templates",
+ tool_config_file =3D ','.join( [ galaxy_tool_conf_file,=
galaxy_shed_tool_conf_file ] ),
+ tool_data_path =3D tool_data_path,
+ tool_data_table_config_path =3D galaxy_tool_data_table_=
conf_file,
+ tool_dependency_dir =3D tool_dependency_dir,
+ tool_path =3D tool_path,
+ tool_parse_help =3D False,
+ tool_sheds_config_file =3D galaxy_tool_sheds_conf_file,
+ update_integrated_tool_panel =3D False,
+ use_heartbeat =3D False )
+ galaxy_config_file =3D os.environ.get( 'GALAXY_INSTALL_TEST_INI_FILE',=
None )
+ # If the user has passed in a path for the .ini file, do not overwrite=
it.
+ if not galaxy_config_file:
+ galaxy_config_file =3D os.path.join( galaxy_test_tmp_dir, 'install=
_test_tool_shed_repositories_wsgi.ini' )
+ config_items =3D []
+ for label in kwargs:
+ config_tuple =3D label, kwargs[ label ]
+ config_items.append( config_tuple )
+ # Write a temporary file, based on universe_wsgi.ini.sample, using=
the configuration options defined above.
+ generate_config_file( 'universe_wsgi.ini.sample', galaxy_config_fi=
le, config_items )
+ kwargs[ 'tool_config_file' ] =3D [ galaxy_tool_conf_file, galaxy_shed_=
tool_conf_file ]
+ # Set the global_conf[ '__file__' ] option to the location of the temp=
orary .ini file, which gets passed to set_metadata.sh.
+ kwargs[ 'global_conf' ] =3D get_webapp_global_conf()
+ kwargs[ 'global_conf' ][ '__file__' ] =3D galaxy_config_file
# ---- Build Galaxy Application --------------------------------------=
------------=20
- global_conf =3D { '__file__' : 'universe_wsgi.ini.sample' }
if not database_connection.startswith( 'sqlite://' ):
kwargs[ 'database_engine_option_max_overflow' ] =3D '20'
kwargs[ 'database_engine_option_pool_size' ] =3D '10'
- app =3D UniverseApplication( admin_users =3D 'test(a)bx.psu.edu',
- allow_user_creation =3D True,
- allow_user_deletion =3D True,
- allow_library_path_paste =3D True,
- database_connection =3D database_connection,
- datatype_converters_config_file =3D "dataty=
pe_converters_conf.xml.sample",
- file_path =3D galaxy_file_path,
- global_conf =3D global_conf,
- id_secret =3D galaxy_encode_secret,
- job_queue_workers =3D 5,
- log_destination =3D "stdout",
- migrated_tools_config =3D galaxy_migrated_t=
ool_conf_file,
- new_file_path =3D galaxy_tempfiles,
- running_functional_tests=3DTrue,
- shed_tool_data_table_config =3D shed_tool_d=
ata_table_conf_file,
- shed_tool_path =3D galaxy_shed_tool_path,
- template_path =3D "templates",
- tool_config_file =3D [ galaxy_tool_conf_fil=
e, galaxy_shed_tool_conf_file ],
- tool_data_path =3D tool_data_path,
- tool_data_table_config_path =3D galaxy_tool=
_data_table_conf_file,
- tool_dependency_dir =3D tool_dependency_dir,
- tool_path =3D tool_path,
- tool_parse_help =3D False,
- tool_sheds_config_file =3D galaxy_tool_shed=
s_conf_file,
- update_integrated_tool_panel =3D False,
- use_heartbeat =3D False,
- **kwargs )
+ kwargs[ 'config_file' ] =3D galaxy_config_file
+ app =3D UniverseApplication( **kwargs )
=20
log.info( "Embedded Galaxy application started" )
=20
# ---- Run galaxy webserver ------------------------------------------=
------------
server =3D None
- webapp =3D buildapp.app_factory( dict( database_file=3Ddatabase_connec=
tion ),
- use_translogger=3DFalse,
- static_enabled=3DFalse,
- app=3Dapp )
+ global_conf =3D get_webapp_global_conf()
+ global_conf[ 'database_file' ] =3D database_connection
+ webapp =3D buildapp.app_factory( global_conf,
+ use_translogger=3DFalse,
+ static_enabled=3DSTATIC_ENABLED,
+ app=3Dapp )
=20
# Serve the app on a specified or random port.
if galaxy_test_port is not None:
@@ -976,6 +1057,7 @@
repositories_passed.append( dict( name=3Dname, own=
er=3Downer, changeset_revision=3Dchangeset_revision ) )
params[ 'tools_functionally_correct' ] =3D True
params[ 'do_not_test' ] =3D False
+ params[ 'test_install_error' ] =3D False
register_test_result( galaxy_tool_shed_url,=20
metadata_revision_id,=20
repository_status,=20
@@ -1027,6 +1109,7 @@
repositories_failed.append( dict( name=3Dname, own=
er=3Downer, changeset_revision=3Dchangeset_revision ) )
set_do_not_test =3D not is_latest_downloadable_rev=
ision( galaxy_tool_shed_url, repository_info_dict )
params[ 'tools_functionally_correct' ] =3D False
+ params[ 'test_install_error' ] =3D False
params[ 'do_not_test' ] =3D str( set_do_not_test )
register_test_result( galaxy_tool_shed_url,=20
metadata_revision_id,=20
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c test/unit/datatypes/dataproviders/tempfilecache.py
--- /dev/null
+++ b/test/unit/datatypes/dataproviders/tempfilecache.py
@@ -0,0 +1,47 @@
+
+import os
+import tempfile
+
+import logging
+logging.getLogger( __name__ )
+log =3D logging
+
+class TempFileCache( object ):
+ """
+ Creates and caches tempfiles with/based-on the given contents.
+ """
+ def __init__( self, logger=3DNone ):
+ if logger:
+ global log
+ log =3D logger
+ super( TempFileCache, self ).__init__()
+ self.clear()
+
+ def clear( self ):
+ self.delete_tmpfiles()
+ self._content_dict =3D {}
+
+ def create_tmpfile( self, contents ):
+ if not hasattr( self, '_content_dict' ):
+ self.set_up_tmpfiles()
+
+ if contents not in self._content_dict:
+ # create a named tmp and write contents to it, return filename
+ tmpfile =3D tempfile.NamedTemporaryFile( delete=3DFalse )
+ tmpfile.write( contents )
+ tmpfile.close()
+ log.debug( 'created tmpfile.name: %s', tmpfile.name )
+ self._content_dict[ contents ] =3D tmpfile.name
+
+ else:
+ log.debug( '(cached): %s', self._content_dict[ contents ] )
+ return self._content_dict[ contents ]
+
+ def delete_tmpfiles( self ):
+ if not hasattr( self, '_content_dict' ) or not self._content_dict:
+ return
+ for tmpfile_contents in self._content_dict:
+ tmpfile =3D self._content_dict[ tmpfile_contents ]
+ if os.path.exists( tmpfile ):
+ log.debug( 'unlinking tmpfile: %s', tmpfile )
+ os.unlink( tmpfile )
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c test/unit/datatypes/dataproviders/test_base_dataproviders=
.py
--- /dev/null
+++ b/test/unit/datatypes/dataproviders/test_base_dataproviders.py
@@ -0,0 +1,370 @@
+"""
+Unit tests for base DataProviders.
+.. seealso:: galaxy.datatypes.dataproviders.base
+"""
+# currently because of dataproviders.dataset importing galaxy.model this d=
oesn't work
+#TODO: fix imports there after dist and retry
+
+#TODO: fix off by ones in FilteredDataProvider counters
+
+import unittest
+import StringIO
+
+import tempfilecache
+import utility
+
+log =3D utility.set_up_filelogger( __name__ + '.log' )
+
+utility.add_galaxy_lib_to_path( '/test/unit/datatypes/dataproviders' )
+from galaxy.datatypes import dataproviders
+
+
+class BaseTestCase( unittest.TestCase ):
+ default_file_contents =3D """
+ One
+ Two
+ Three
+ """
+
+ @classmethod
+ def setUpClass( cls ):
+ log.debug( 'CLASS %s %s', ( '_' * 40 ), cls.__name__ )
+
+ @classmethod
+ def tearDownClass( cls ):
+ log.debug( 'CLASS %s %s\n\n', ( '_' * 40 ), cls.__name__ )
+
+ def __init__( self, *args ):
+ unittest.TestCase.__init__( self, *args )
+ self.tmpfiles =3D tempfilecache.TempFileCache( log )
+
+ def setUp( self ):
+ log.debug( 'BEGIN %s %s', ( '.' * 40 ), self._testMethodName )
+ if self._testMethodDoc:
+ log.debug( ' """%s"""', self._testMethodDoc.strip() )
+
+ def tearDown( self ):
+ self.tmpfiles.clear()
+ log.debug( 'END\n' )
+
+ def format_tmpfile_contents( self, contents=3DNone ):
+ contents =3D contents or self.default_file_contents
+ contents =3D utility.clean_multiline_string( contents )
+ log.debug( 'file contents:\n%s', contents )
+ return contents
+
+
+class Test_BaseDataProvider( BaseTestCase ):
+ provider_class =3D dataproviders.base.DataProvider
+
+ def contents_provider_and_data( self,
+ filename=3DNone, contents=3DNone, source=3DNone, *provider_arg=
s, **provider_kwargs ):
+ # to remove boiler plate
+ # returns file content string, provider used, and data list
+ if not filename:
+ contents =3D self.format_tmpfile_contents( contents )
+ filename =3D self.tmpfiles.create_tmpfile( contents )
+ #TODO: if filename, contents =3D=3D None
+ if not source:
+ source =3D open( filename )
+ provider =3D self.provider_class( source, *provider_args, **provid=
er_kwargs )
+ log.debug( 'provider: %s', provider )
+ data =3D list( provider )
+ log.debug( 'data: %s', str( data ) )
+ return ( contents, provider, data )
+
+ def test_iterators( self ):
+ source =3D ( x for x in xrange( 1, 10 ) )
+ provider =3D self.provider_class( source )
+ data =3D list( provider )
+ log.debug( 'data: %s', str( data ) )
+ self.assertEqual( data, [ x for x in xrange( 1, 10 ) ] )
+
+ source =3D [ x for x in xrange( 1, 10 ) ]
+ provider =3D self.provider_class( source )
+ data =3D list( provider )
+ log.debug( 'data: %s', str( data ) )
+ self.assertEqual( data, [ x for x in xrange( 1, 10 ) ] )
+
+ source =3D ( x for x in xrange( 1, 10 ) )
+ provider =3D self.provider_class( source )
+ data =3D list( provider )
+ log.debug( 'data: %s', str( data ) )
+ self.assertEqual( data, [ x for x in xrange( 1, 10 ) ] )
+
+ def test_validate_source( self ):
+ """validate_source should throw an error if the source doesn't hav=
e attr '__iter__'
+ """
+ def non_iterator_dprov( source ):
+ return self.provider_class( source )
+ self.assertRaises( dataproviders.exceptions.InvalidDataProviderSou=
rce,
+ non_iterator_dprov, 'one two three' )
+ self.assertRaises( dataproviders.exceptions.InvalidDataProviderSou=
rce,
+ non_iterator_dprov, 40 )
+
+ def test_writemethods( self ):
+ """should throw an error if any write methods are called
+ """
+ source =3D ( x for x in xrange( 1, 10 ) )
+ provider =3D self.provider_class( source )
+ # should throw error
+ def call_method( provider, method_name, *args ):
+ method =3D getattr( provider, method_name )
+ return method( *args )
+ self.assertRaises( NotImplementedError, call_method, provider, 'tr=
uncate', 20 )
+ self.assertRaises( NotImplementedError, call_method, provider, 'wr=
ite', 'bler' )
+ self.assertRaises( NotImplementedError, call_method, provider, 'wr=
itelines', [ 'one', 'two' ] )
+
+ def test_readlines( self ):
+ """readlines should return all the data in list form
+ """
+ source =3D ( x for x in xrange( 1, 10 ) )
+ provider =3D self.provider_class( source )
+ data =3D provider.readlines()
+ log.debug( 'data: %s', str( data ) )
+ self.assertEqual( data, [ x for x in xrange( 1, 10 ) ] )
+
+ def test_stringio( self ):
+ """should work with StringIO
+ """
+ contents =3D utility.clean_multiline_string( """
+ One
+ Two
+ Three
+ """ )
+ source =3D StringIO.StringIO( contents )
+ provider =3D self.provider_class( source )
+ data =3D list( provider )
+ log.debug( 'data: %s', str( data ) )
+ # provider should call close on file
+ self.assertEqual( ''.join( data ), contents )
+ self.assertTrue( source.closed )
+
+ def test_file( self ):
+ """should work with files
+ """
+ ( contents, provider, data ) =3D self.contents_provider_and_data()
+ self.assertEqual( ''.join( data ), contents )
+ # provider should call close on file
+ self.assertTrue( isinstance( provider.source, file ) )
+ self.assertTrue( provider.source.closed )
+
+
+class Test_FilteredDataProvider( Test_BaseDataProvider ):
+ provider_class =3D dataproviders.base.FilteredDataProvider
+
+ def assertCounters( self, provider, read, valid, returned ):
+ self.assertEqual( provider.num_data_read, read )
+ self.assertEqual( provider.num_valid_data_read, valid )
+ self.assertEqual( provider.num_data_returned, returned )
+
+ def test_counters( self ):
+ """should count: lines read, lines that passed the filter, lines r=
eturned
+ """
+ ( contents, provider, data ) =3D self.contents_provider_and_data()
+ self.assertCounters( provider, 3, 3, 3 )
+
+ def test_filter_fn( self ):
+ """should filter out lines using filter_fn and set counters proper=
ly
+ based on filter
+ """
+ def filter_ts( string ):
+ if string.lower().startswith( 't' ):
+ return None
+ return string
+ ( contents, provider, data ) =3D self.contents_provider_and_data( =
filter_fn=3Dfilter_ts )
+ self.assertCounters( provider, 3, 1, 1 )
+
+
+class Test_LimitedOffsetDataProvider( Test_FilteredDataProvider ):
+ provider_class =3D dataproviders.base.LimitedOffsetDataProvider
+
+ def test_offset_1( self ):
+ """when offset is 1, should skip first
+ """
+ ( contents, provider, data ) =3D self.contents_provider_and_data( =
offset=3D1 )
+ self.assertEqual( data, [ 'Two\n', 'Three\n' ] )
+ self.assertCounters( provider, 3, 3, 2 )
+
+ def test_offset_all( self ):
+ """when offset >=3D num lines, should return empty list
+ """
+ ( contents, provider, data ) =3D self.contents_provider_and_data( =
offset=3D4 )
+ self.assertEqual( data, [] )
+ self.assertCounters( provider, 3, 3, 0 )
+
+ def test_offset_none( self ):
+ """when offset is 0, should return all
+ """
+ ( contents, provider, data ) =3D self.contents_provider_and_data( =
offset=3D0 )
+ self.assertEqual( ''.join( data ), contents )
+ self.assertCounters( provider, 3, 3, 3 )
+
+ def test_offset_negative( self ):
+ """when offset is negative, should return all
+ """
+ ( contents, provider, data ) =3D self.contents_provider_and_data( =
offset=3D-1 )
+ self.assertEqual( ''.join( data ), contents )
+ self.assertCounters( provider, 3, 3, 3 )
+
+ def test_limit_1( self ):
+ """when limit is one, should return first
+ """
+ ( contents, provider, data ) =3D self.contents_provider_and_data( =
limit=3D1 )
+ self.assertEqual( data, [ 'One\n' ] )
+ #TODO: currently reads 2 in all counters before ending
+ #self.assertCounters( provider, 1, 1, 1 )
+
+ def test_limit_all( self ):
+ """when limit >=3D num lines, should return all
+ """
+ ( contents, provider, data ) =3D self.contents_provider_and_data( =
limit=3D4 )
+ self.assertEqual( ''.join( data ), contents )
+ self.assertCounters( provider, 3, 3, 3 )
+
+ def test_limit_zero( self ):
+ """when limit >=3D num lines, should return empty list
+ """
+ ( contents, provider, data ) =3D self.contents_provider_and_data( =
limit=3D0 )
+ self.assertEqual( data, [] )
+ #TODO: currently reads 1 before ending
+ self.assertCounters( provider, 3, 0, 0 )
+
+ def test_limit_zero( self ):
+ """when limit is None, should return all
+ """
+ ( contents, provider, data ) =3D self.contents_provider_and_data( =
limit=3DNone )
+ self.assertEqual( ''.join( data ), contents )
+ self.assertCounters( provider, 3, 3, 3 )
+
+ #TODO: somehow re-use tmpfile here
+ def test_limit_with_offset( self ):
+ def limit_offset_combo( limit, offset, data_should_be, read, valid=
, returned ):
+ ( contents, provider, data ) =3D self.contents_provider_and_da=
ta( limit=3Dlimit, offset=3Doffset )
+ self.assertEqual( data, data_should_be )
+ #self.assertCounters( provider, read, valid, returned )
+ test_data =3D [
+ ( 0, 0, [], 0, 0, 0 ),
+ ( 1, 0, [ 'One\n' ], 1, 1, 1 ),
+ ( 2, 0, [ 'One\n', 'Two\n' ], 2, 2, 2 ),
+ ( 3, 0, [ 'One\n', 'Two\n', 'Three\n' ], 3, 3, 3 ),
+ ( 1, 1, [ 'Two\n' ], 1, 1, 1 ),
+ ( 2, 1, [ 'Two\n', 'Three\n' ], 2, 2, 2 ),
+ ( 3, 1, [ 'Two\n', 'Three\n' ], 2, 2, 2 ),
+ ( 1, 2, [ 'Three\n' ], 1, 1, 1 ),
+ ( 2, 2, [ 'Three\n' ], 1, 1, 1 ),
+ ( 3, 2, [ 'Three\n' ], 1, 1, 1 ),
+ ]
+ for test in test_data:
+ log.debug( 'limit_offset_combo: %s', ', '.join([ str( e ) for =
e in test ]) )
+ limit_offset_combo( *test )
+
+ def test_limit_with_offset_and_filter( self ):
+ def limit_offset_combo( limit, offset, data_should_be, read, valid=
, returned ):
+ def only_ts( string ):
+ if not string.lower().startswith( 't' ):
+ return None
+ return string
+ ( contents, provider, data ) =3D self.contents_provider_and_da=
ta(
+ limit=3Dlimit, offset=3Doffset, filter_fn=3Donly_ts )
+ self.assertEqual( data, data_should_be )
+ #self.assertCounters( provider, read, valid, returned )
+ test_data =3D [
+ ( 0, 0, [], 0, 0, 0 ),
+ ( 1, 0, [ 'Two\n' ], 1, 1, 1 ),
+ ( 2, 0, [ 'Two\n', 'Three\n' ], 2, 2, 2 ),
+ ( 3, 0, [ 'Two\n', 'Three\n' ], 2, 2, 2 ),
+ ( 1, 1, [ 'Three\n' ], 1, 1, 1 ),
+ ( 2, 1, [ 'Three\n' ], 1, 1, 1 ),
+ ( 1, 2, [], 0, 0, 0 ),
+ ]
+ for test in test_data:
+ log.debug( 'limit_offset_combo: %s', ', '.join([ str( e ) for =
e in test ]) )
+ limit_offset_combo( *test )
+
+
+class Test_MultiSourceDataProvider( BaseTestCase ):
+ provider_class =3D dataproviders.base.MultiSourceDataProvider
+
+ def contents_and_tmpfile( self, contents=3DNone ):
+ #TODO: hmmmm...
+ contents =3D contents or self.default_file_contents
+ contents =3D utility.clean_multiline_string( contents )
+ return ( contents, self.tmpfiles.create_tmpfile( contents ) )
+
+ def test_multiple_sources( self ):
+ # clean the following contents, write them to tmpfiles, open them,
+ # and pass as a list to the provider
+ contents =3D [
+ """
+ One
+ Two
+ Three
+ Four
+ Five
+ """,
+ """
+ Six
+ Seven
+ Eight
+ Nine
+ Ten
+ """,
+ """
+ Eleven
+ Twelve! (<-- http://youtu.be/JZshZp-cxKg)
+ """
+ ]
+ contents =3D [ utility.clean_multiline_string( c ) for c in conten=
ts ]
+ source_list =3D [ open( self.tmpfiles.create_tmpfile( c ) ) for c =
in contents ]
+
+ provider =3D self.provider_class( source_list )
+ log.debug( 'provider: %s', provider )
+ data =3D list( provider )
+ log.debug( 'data: %s', str( data ) )
+ self.assertEqual( ''.join( data ), ''.join( contents) )
+
+ def test_multiple_compound_sources( self ):
+ # clean the following contents, write them to tmpfiles, open them,
+ # and pass as a list to the provider
+ contents =3D [
+ """
+ One
+ Two
+ Three
+ Four
+ Five
+ """,
+ """
+ Six
+ Seven
+ Eight
+ Nine
+ Ten
+ """,
+ """
+ Eleven
+ Twelve! (<-- http://youtu.be/JZshZp-cxKg)
+ """
+ ]
+ contents =3D [ utility.clean_multiline_string( c ) for c in conten=
ts ]
+ source_list =3D [ open( self.tmpfiles.create_tmpfile( c ) ) for c =
in contents ]
+
+ def no_Fs( string ):
+ return None if string.startswith( 'F' ) else string
+ def no_youtube( string ):
+ return None if ( 'youtu.be' in string ) else string
+ source_list =3D [
+ dataproviders.base.LimitedOffsetDataProvider( source_list[0], =
filter_fn=3Dno_Fs, limit=3D2, offset=3D1 ),
+ dataproviders.base.LimitedOffsetDataProvider( source_list[1], =
limit=3D1, offset=3D3 ),
+ dataproviders.base.FilteredDataProvider( source_list[2], filte=
r_fn=3Dno_youtube ),
+ ]
+ provider =3D self.provider_class( source_list )
+ log.debug( 'provider: %s', provider )
+ data =3D list( provider )
+ log.debug( 'data: %s', str( data ) )
+ self.assertEqual( ''.join( data ), 'Two\nThree\nNine\nEleven\n' )
+
+
+if __name__ =3D=3D '__main__':
+ unittest.main()
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c test/unit/datatypes/dataproviders/utility.py
--- /dev/null
+++ b/test/unit/datatypes/dataproviders/utility.py
@@ -0,0 +1,45 @@
+"""
+Unit test utilities.
+"""
+
+import os
+import sys
+import logging
+import textwrap
+
+def set_up_filelogger( logname, level=3Dlogging.DEBUG ):
+ """
+ Sets up logging to a file named `logname`
+ (removing it first if it already exists).
+
+ Usable with 'nosetests' to get logging msgs from failed tests
+ (no logfile created).
+ Usable with 'nosetests --nologcapture' to get logging msgs for all tes=
ts
+ (in logfile).
+ """
+ if os.path.exists( logname ): os.unlink( logname )
+ logging.basicConfig( filename=3Dlogname, level=3Dlogging.DEBUG )
+ return logging
+
+def add_galaxy_lib_to_path( this_dir_relative_to_root ):
+ """
+ Adds `<galaxy>/lib` to `sys.path` given the scripts directory relative
+ to `<galaxy>`.
+ .. example::
+ utility.add_galaxy_lib_to_path( '/test/unit/datatypes/dataprovider=
s' )
+ """
+ glx_lib =3D os.path.join( os.getcwd().replace( this_dir_relative_to_ro=
ot, '' ), 'lib' )
+ sys.path.append( glx_lib )
+
+def clean_multiline_string( multiline_string, sep=3D'\n' ):
+ """
+ Dedent, split, remove first and last empty lines, rejoin.
+ """
+ multiline_string =3D textwrap.dedent( multiline_string )
+ string_list =3D multiline_string.split( sep )
+ if not string_list[0]:
+ string_list =3D string_list[1:]
+ if not string_list[-1]:
+ string_list =3D string_list[:-1]
+ #return '\n'.join( docstrings )
+ return ''.join([ ( s + '\n' ) for s in string_list ])
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c test/unit/test_dataproviders.pyc
Binary file test/unit/test_dataproviders.pyc has changed
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c test/unit/test_tool_loader.pyc
Binary file test/unit/test_tool_loader.pyc has changed
diff -r a360e1b7b506450385be74b2c6b7762d3e794bbd -r 79ae7df72fba2e141791bdb=
8fdf2bb372fa3787c tools/ngs_rna/cuffdiff_wrapper.py
--- a/tools/ngs_rna/cuffdiff_wrapper.py
+++ /dev/null
@@ -1,241 +0,0 @@
-#!/usr/bin/env python
-
-# Wrapper supports Cuffdiff versions v1.3.0-v2.0
-
-import optparse, os, shutil, subprocess, sys, tempfile
-
-def group_callback( option, op_str, value, parser ):
- groups =3D []
- flist =3D []
- for arg in parser.rargs:
- arg =3D arg.strip()
- if arg[0] is "-":
- break
- elif arg[0] is ",":
- groups.append(flist)
- flist =3D []
- else:
- flist.append(arg)
- groups.append(flist)
-
- setattr(parser.values, option.dest, groups)
- =20
-def label_callback( option, op_str, value, parser ):
- labels =3D []
- for arg in parser.rargs:
- arg =3D arg.strip()
- if arg[0] is "-":
- break
- else:
- labels.append(arg)
-
- setattr(parser.values, option.dest, labels)
-
-def stop_err( msg ):
- sys.stderr.write( "%s\n" % msg )
- sys.exit()
- =20
-# Copied from sam_to_bam.py:
-def check_seq_file( dbkey, cached_seqs_pointer_file ):
- seq_path =3D ''
- for line in open( cached_seqs_pointer_file ):
- line =3D line.rstrip( '\r\n' )
- if line and not line.startswith( '#' ) and line.startswith( 'index=
' ):
- fields =3D line.split( '\t' )
- if len( fields ) < 3:
- continue
- if fields[1] =3D=3D dbkey:
- seq_path =3D fields[2].strip()
- break
- return seq_path
-
-def __main__():
- #Parse Command Line
- parser =3D optparse.OptionParser()
- =20
- # Cuffdiff options.
- parser.add_option( '-s', '--inner-dist-std-dev', dest=3D'inner_dist_st=
d_dev', help=3D'The standard deviation for the distribution on inner distan=
ces between mate pairs. The default is 20bp.' )
- parser.add_option( '-p', '--num-threads', dest=3D'num_threads', help=
=3D'Use this many threads to align reads. The default is 1.' )
- parser.add_option( '-m', '--inner-mean-dist', dest=3D'inner_mean_dist'=
, help=3D'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. The default is 4=
5bp.')
- parser.add_option( '-c', '--min-alignment-count', dest=3D'min_alignmen=
t_count', help=3D'The minimum number of alignments in a locus for needed to=
conduct significance testing on changes in that locus observed between sam=
ples. If no testing is performed, changes in the locus are deemed not signf=
icant, and the locus\' observed changes don\'t contribute to correction for=
multiple testing. The default is 1,000 fragment alignments (up to 2,000 pa=
ired reads).' )
- parser.add_option( '--FDR', dest=3D'FDR', help=3D'The allowed false di=
scovery rate. The default is 0.05.' )
- parser.add_option( '-u', '--multi-read-correct', dest=3D'multi_read_co=
rrect', action=3D"store_true", help=3D'Tells Cufflinks to do an initial est=
imation procedure to more accurately weight reads mapping to multiple locat=
ions in the genome')
- parser.add_option( '--library-norm-method', dest=3D'library_norm_metho=
d' )
- parser.add_option( '--dispersion-method', dest=3D'dispersion_method' )
-
- # Advanced Options:=09
- parser.add_option( '--num-importance-samples', dest=3D'num_importance_=
samples', help=3D'Sets the number of importance samples generated for each =
locus during abundance estimation. Default: 1000' )
- parser.add_option( '--max-mle-iterations', dest=3D'max_mle_iterations'=
, help=3D'Sets the number of iterations allowed during maximum likelihood e=
stimation of abundances. Default: 5000' )
- =20
- # Wrapper / Galaxy options.
- parser.add_option( '-f', '--files', dest=3D'groups', action=3D"callbac=
k", callback=3Dgroup_callback, help=3D"Groups to be processed, groups are s=
eparated by spaces, replicates in a group comma separated. group1_rep1,grou=
p1_rep2 group2_rep1,group2_rep2, ..., groupN_rep1, groupN_rep2" )
- parser.add_option( '-A', '--inputA', dest=3D'inputA', help=3D'A transc=
ript GTF file produced by cufflinks, cuffcompare, or other source.')
- parser.add_option( '-1', '--input1', dest=3D'input1', help=3D'File of =
RNA-Seq read alignments in the SAM format. SAM is a standard short read ali=
gnment, that allows aligners to attach custom tags to individual alignments=
, and Cufflinks requires that the alignments you supply have some of these =
tags. Please see Input formats for more details.' )
- parser.add_option( '-2', '--input2', dest=3D'input2', help=3D'File of =
RNA-Seq read alignments in the SAM format. SAM is a standard short read ali=
gnment, that allows aligners to attach custom tags to individual alignments=
, and Cufflinks requires that the alignments you supply have some of these =
tags. Please see Input formats for more details.' )
-
- # Label options
- parser.add_option('-L', '--labels', dest=3D'labels', action=3D"callbac=
k", callback=3Dlabel_callback, help=3D"Labels for the groups the replicates=
are in.")
- =20
- # Normalization options.
- parser.add_option( "-N", "--quartile-normalization", dest=3D"do_normal=
ization", action=3D"store_true" )
-
- # Bias correction options.
- parser.add_option( '-b', dest=3D'do_bias_correction', action=3D"store_=
true", help=3D'Providing Cufflinks with a multifasta file via this option i=
nstructs it to run our new bias detection and correction algorithm which ca=
n significantly improve accuracy of transcript abundance estimates.')
- parser.add_option( '', '--dbkey', dest=3D'dbkey', help=3D'The build of=
the reference dataset' )
- parser.add_option( '', '--index_dir', dest=3D'index_dir', help=3D'GALA=
XY_DATA_INDEX_DIR' )
- parser.add_option( '', '--ref_file', dest=3D'ref_file', help=3D'The re=
ference dataset from the history' )
-
- # Outputs.
- parser.add_option( "--isoforms_fpkm_tracking_output", dest=3D"isoforms=
_fpkm_tracking_output" )
- parser.add_option( "--genes_fpkm_tracking_output", dest=3D"genes_fpkm_=
tracking_output" )
- parser.add_option( "--cds_fpkm_tracking_output", dest=3D"cds_fpkm_trac=
king_output" )
- parser.add_option( "--tss_groups_fpkm_tracking_output", dest=3D"tss_gr=
oups_fpkm_tracking_output" )
- parser.add_option( "--isoforms_exp_output", dest=3D"isoforms_exp_outpu=
t" )
- parser.add_option( "--genes_exp_output", dest=3D"genes_exp_output" )
- parser.add_option( "--tss_groups_exp_output", dest=3D"tss_groups_exp_o=
utput" )
- parser.add_option( "--cds_exp_fpkm_tracking_output", dest=3D"cds_exp_f=
pkm_tracking_output" )
- parser.add_option( "--splicing_diff_output", dest=3D"splicing_diff_out=
put" )
- parser.add_option( "--cds_diff_output", dest=3D"cds_diff_output" )
- parser.add_option( "--promoters_diff_output", dest=3D"promoters_diff_o=
utput" )
- =20
- (options, args) =3D parser.parse_args()
- =20
- # output version # of tool
- try:
- tmp =3D tempfile.NamedTemporaryFile().name
- tmp_stdout =3D open( tmp, 'wb' )
- proc =3D subprocess.Popen( args=3D'cuffdiff --no-update-check 2>&1=
', shell=3DTrue, stdout=3Dtmp_stdout )
- tmp_stdout.close()
- returncode =3D proc.wait()
- stdout =3D None
- for line in open( tmp_stdout.name, 'rb' ):
- if line.lower().find( 'cuffdiff v' ) >=3D 0:
- stdout =3D line.strip()
- break
- if stdout:
- sys.stdout.write( '%s\n' % stdout )
- else:
- raise Exception
- except:
- sys.stdout.write( 'Could not determine Cuffdiff version\n' )
- =20
- # If doing bias correction, set/link to sequence file.
- if options.do_bias_correction:
- if options.ref_file !=3D 'None':
- # Sequence data from history.
- # Create symbolic link to ref_file so that index will be creat=
ed in working directory.
- seq_path =3D "ref.fa"
- os.symlink( options.ref_file, seq_path )
- else:
- # Sequence data from loc file.
- cached_seqs_pointer_file =3D os.path.join( options.index_dir, =
'sam_fa_indices.loc' )
- if not os.path.exists( cached_seqs_pointer_file ):
- stop_err( 'The required file (%s) does not exist.' % cache=
d_seqs_pointer_file )
- # If found for the dbkey, seq_path will look something like /g=
alaxy/data/equCab2/sam_index/equCab2.fa,
- # and the equCab2.fa file will contain fasta sequences.
- seq_path =3D check_seq_file( options.dbkey, cached_seqs_pointe=
r_file )
- if seq_path =3D=3D '':
- stop_err( 'No sequence data found for dbkey %s, so bias co=
rrection cannot be used.' % options.dbkey ) =20
- =20
- # Build command.
- =20
- # Base; always use quiet mode to avoid problems with storing log outpu=
t.
- cmd =3D "cuffdiff --no-update-check -q"
- =20
- # Add options.
- if options.library_norm_method:
- cmd +=3D ( " --library-norm-method %s" % options.library_norm_meth=
od )
- if options.dispersion_method:
- cmd +=3D ( " --dispersion-method %s" % options.dispersion_method )
- if options.inner_dist_std_dev:
- cmd +=3D ( " -s %i" % int ( options.inner_dist_std_dev ) )
- if options.num_threads:
- cmd +=3D ( " -p %i" % int ( options.num_threads ) )
- if options.inner_mean_dist:
- cmd +=3D ( " -m %i" % int ( options.inner_mean_dist ) )
- if options.min_alignment_count:
- cmd +=3D ( " -c %i" % int ( options.min_alignment_count ) )
- if options.FDR:
- cmd +=3D ( " --FDR %f" % float( options.FDR ) )
- if options.multi_read_correct:
- cmd +=3D ( " -u" )
- if options.num_importance_samples:
- cmd +=3D ( " --num-importance-samples %i" % int ( options.num_impo=
rtance_samples ) )
- if options.max_mle_iterations:
- cmd +=3D ( " --max-mle-iterations %i" % int ( options.max_mle_iter=
ations ) )
- if options.do_normalization:
- cmd +=3D ( " -N" )
- if options.do_bias_correction:
- cmd +=3D ( " -b %s" % seq_path )
- =20
- # Add inputs.
- # For replicate analysis: group1_rep1,group1_rep2 groupN_rep1,groupN_r=
ep2
- if options.groups:
- cmd +=3D " --labels "
- for label in options.labels:
- cmd +=3D '"%s",' % label
- cmd =3D cmd[:-1]
-
- cmd +=3D " " + options.inputA + " "
-
- for group in options.groups:
- for filename in group:
- cmd +=3D filename + ","
- cmd =3D cmd[:-1] + " "
- else:=20
- cmd +=3D " " + options.inputA + " " + options.input1 + " " + optio=
ns.input2
- =20
- # Debugging.
- print cmd
-
- # Run command.
- try:
- tmp_name =3D tempfile.NamedTemporaryFile().name
- tmp_stderr =3D open( tmp_name, 'wb' )
- proc =3D subprocess.Popen( args=3Dcmd, shell=3DTrue, stderr=3Dtmp_=
stderr.fileno() )
- returncode =3D proc.wait()
- tmp_stderr.close()
- =20
- # Get stderr, allowing for case where it's very large.
- tmp_stderr =3D open( tmp_name, 'rb' )
- stderr =3D ''
- buffsize =3D 1048576
- try:
- while True:
- stderr +=3D tmp_stderr.read( buffsize )
- if not stderr or len( stderr ) % buffsize !=3D 0:
- break
- except OverflowError:
- pass
- tmp_stderr.close()
- =20
- # Error checking.
- if returncode !=3D 0:
- raise Exception, stderr
- =20
- # check that there are results in the output file
- if len( open( "isoforms.fpkm_tracking", 'rb' ).read().strip() ) =
=3D=3D 0:
- raise Exception, 'The main output file is empty, there may be =
an error with your input file or settings.'
- except Exception, e:
- stop_err( 'Error running cuffdiff. ' + str( e ) )
-
- =20
- # Copy output files to specified files.
- try:
- shutil.copyfile( "isoforms.fpkm_tracking", options.isoforms_fpkm_t=
racking_output )
- shutil.copyfile( "genes.fpkm_tracking", options.genes_fpkm_trackin=
g_output )
- shutil.copyfile( "cds.fpkm_tracking", options.cds_fpkm_tracking_ou=
tput )
- shutil.copyfile( "tss_groups.fpkm_tracking", options.tss_groups_fp=
km_tracking_output )
- shutil.copyfile( "isoform_exp.diff", options.isoforms_exp_output )
- shutil.copyfile( "gene_exp.diff", options.genes_exp_output )
- shutil.copyfile( "tss_group_exp.diff", options.tss_groups_exp_outp=
ut )
- shutil.copyfile( "splicing.diff", options.splicing_diff_output )
- shutil.copyfile( "cds.diff", options.cds_diff_output )
- shutil.copyfile( "cds_exp.diff", options.cds_exp_fpkm_tracking_out=
put )
- shutil.copyfile( "promoters.diff", options.promoters_diff_output )=
=20
- except Exception, e:
- stop_err( 'Error in cuffdiff:\n' + str( e ) )
-
-if __name__=3D=3D"__main__": __main__()
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/galaxy/galaxy-central/commits/40c9834811eb/
Changeset: 40c9834811eb
User: saketkc
Date: 2013-08-06 09:31:21
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r cf53a00bcf1d279072ec279e6531f211992b4f3e -r 40c9834811ebfbefb423155=
3c922ff4c44905c63 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/d33f8c5396a8/
Changeset: d33f8c5396a8
User: saketkc
Date: 2013-08-07 15:21:51
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r f33c054d6d5b75ae545248d71ec559d74b4fa636 -r d33f8c5396a8825b450432a=
8c443e1592a360885 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/a968c0cae563/
Changeset: a968c0cae563
User: saketkc
Date: 2013-08-28 19:15:32
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 22a4f03c1fe40dedcb7e6f11510d58ada8e9c458 -r a968c0cae5639f3be5ffdd9=
31df909c215f43a43 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/4c1eb0c91fc6/
Changeset: 4c1eb0c91fc6
User: saketkc
Date: 2013-08-31 18:30:53
Summary: Automated merge with ssh://bitbucket.org/galaxy/galaxy-central
Affected #: 1 file
diff -r 0470feeb593f9797fa9fd19dfdac4751a7ca788b -r 4c1eb0c91fc6e3085948ef1=
6eb88d18ea626e7d3 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[1])
https://bitbucket.org/galaxy/galaxy-central/commits/dcd9809d0239/
Changeset: dcd9809d0239
User: jgoecks
Date: 2013-09-11 18:16:14
Summary: Merged in saketkc/galaxy-central (pull request #184)
VCFTools Incompatible with VCF4.1
Affected #: 1 file
diff -r 228f1b4066be9fc49f6f07ff6867566836134c67 -r dcd9809d0239c7dc80cec3b=
2a01d7bded4a8c088 tools/vcf_tools/vcfClass.py
--- a/tools/vcf_tools/vcfClass.py
+++ b/tools/vcf_tools/vcfClass.py
@@ -12,12 +12,13 @@
self.hasHeader =3D True
self.headerText =3D ""
self.headerTitles =3D ""
+ self.vcfFormat =3D ""
#self.headerInfoText =3D ""
#self.headerFormatText =3D ""
=20
# Store the info and format tags as well as the lines that describe
# them in a dictionary.
- self.numberDataSets =3D 0=20
+ self.numberDataSets =3D 0
self.includedDataSets =3D {}
self.infoHeaderTags =3D {}
self.infoHeaderString =3D {}
@@ -63,6 +64,7 @@
# Determine the type of information in the header line.
def getHeaderLine(self, filename, writeOut):
self.headerLine =3D self.filehandle.readline().rstrip("\n")
+ if self.headerLine.startswith("##fileformat"): success =3D self.getvcf=
Format()
if self.headerLine.startswith("##INFO"): success =3D self.headerInfo(w=
riteOut, "info")
elif self.headerLine.startswith("##FORMAT"): success =3D self.headerIn=
fo(writeOut, "format")
elif self.headerLine.startswith("##FILE"): success =3D self.headerFile=
s(writeOut)
@@ -72,6 +74,18 @@
=20
return success
=20
+# Read VCF format
+ def getvcfFormat(self):
+ try:
+ self.vcfFormat =3D self.headerLine.split("=3D",1)[1]
+ self.vcfFormat =3D float( self.vcfFormat.split("VCFv",1)[1] )## =
Extract the version number rather than the whole string
+ except IndexError:
+ print >> sys.stderr, "\nError parsing the fileformat"
+ print >> sys.stderr, "The following fileformat header is wrongly=
formatted: ", self.headerLine
+ exit(1)
+ return True
+
+
# Read information on an info field from the header line.
def headerInfo(self, writeOut, lineType):
tag =3D self.headerLine.split("=3D",1)
@@ -93,11 +107,15 @@
# an integer or a '.' to indicate variable number of entries.
if tagNumber =3D=3D ".": tagNumber =3D "variable"
else:
- try: tagNumber =3D int(tagNumber)
- except ValueError:
- print >> sys.stderr, "\nError parsing header. Problem with info t=
ag:", tagID
- print >> sys.stderr, "Number of fields associated with this tag is=
not an integer or '.'"
- exit(1)
+ if self.vcfFormat<4.1:
+
+ try:
+ tagNumber =3D int(tagNumber)
+
+ except ValueError:
+ print >> sys.stderr, "\nError parsing header. Problem with in=
fo tag:", tagID
+ print >> sys.stderr, "Number of fields associated with this ta=
g is not an integer or '.'"
+ exit(1)
=20
if lineType =3D=3D "info":
self.infoHeaderTags[tagID] =3D tagNumber, tagType, tagDescription
@@ -161,7 +179,7 @@
return False
=20
# If there is no header in the vcf file, close and reopen the
-# file so that the first line is avaiable for parsing as a=20
+# file so that the first line is avaiable for parsing as a
# vcf record.
def noHeader(self, filename, writeOut):
if writeOut: print >> sys.stdout, "No header lines present in", filena=
me
@@ -216,7 +234,7 @@
else: self.hasGenotypes =3D False
=20
# Add the reference sequence to the dictionary. If it didn't previously
-# exist append the reference sequence to the end of the list as well.=20
+# exist append the reference sequence to the end of the list as well.
# This ensures that the order in which the reference sequences appeared
# in the header can be preserved.
if self.referenceSequence not in self.referenceSequences:
@@ -274,7 +292,7 @@
# Check that there are as many fields as in the format field. If not, thi=
s must
# be because the information is not known. In this case, it is permitted =
that
# the genotype information is either . or ./.
- if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):=20
+ if genotypeInfo[0] =3D=3D "./." or genotypeInfo[0] =3D=3D "." and le=
n(self.genotypeFormats) !=3D len(genotypeInfo):
self.genotypeFields[ self.samplesList[i] ] =3D "."
else:
if len(self.genotypeFormats) !=3D len(genotypeInfo):
@@ -381,7 +399,7 @@
=20
# First check that the variant class (VC) is listed as SNP.
vc =3D self.info.split("VC=3D",1)
- if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)=20
+ if vc[1].find(";") !=3D -1: snp =3D vc[1].split(";",1)
else:
snp =3D []
snp.append(vc[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
commit/galaxy-central: guerler: Ensure availability of window.Galaxy variable
by commits-noreply@bitbucket.org 11 Sep '13
by commits-noreply@bitbucket.org 11 Sep '13
11 Sep '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/228f1b4066be/
Changeset: 228f1b4066be
User: guerler
Date: 2013-09-11 18:15:13
Summary: Ensure availability of window.Galaxy variable
Affected #: 2 files
diff -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 -r 228f1b4066be9fc49f6f07ff6867566836134c67 templates/base/base_panels.mako
--- a/templates/base/base_panels.mako
+++ b/templates/base/base_panels.mako
@@ -81,6 +81,9 @@
if (window != window.top)
$('<link href="' + galaxy_config.root + 'static/style/galaxy.frame.masthead.css" rel="stylesheet">').appendTo('head');
+ // start a Galaxy namespace for objects created
+ window.Galaxy = window.Galaxy || {};
+
// console protection
window.console = window.console || {
log : function(){},
diff -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 -r 228f1b4066be9fc49f6f07ff6867566836134c67 templates/webapps/galaxy/galaxy.panels.mako
--- a/templates/webapps/galaxy/galaxy.panels.mako
+++ b/templates/webapps/galaxy/galaxy.panels.mako
@@ -58,6 +58,9 @@
## make sure console exists
<script type="text/javascript">
+ // start a Galaxy namespace for objects created
+ window.Galaxy = window.Galaxy || {};
+
// console protection
window.console = window.console ||
{
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: guerler: Drag&drop multiple file upload, new js-based modal window and dynamic icon menu for master head
by commits-noreply@bitbucket.org 11 Sep '13
by commits-noreply@bitbucket.org 11 Sep '13
11 Sep '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/99cc1ee095c3/
Changeset: 99cc1ee095c3
User: guerler
Date: 2013-09-11 17:25:00
Summary: Drag&drop multiple file upload, new js-based modal window and dynamic icon menu for master head
Affected #: 26 files
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 lib/galaxy/webapps/galaxy/api/history_contents.py
--- a/lib/galaxy/webapps/galaxy/api/history_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/history_contents.py
@@ -6,7 +6,9 @@
from galaxy.web.base.controller import BaseAPIController, url_for
from galaxy.web.base.controller import UsesHistoryDatasetAssociationMixin, UsesHistoryMixin
from galaxy.web.base.controller import UsesLibraryMixin, UsesLibraryMixinItems
+from galaxy.datatypes import sniff
+import os
import logging
log = logging.getLogger( __name__ )
@@ -160,42 +162,118 @@
:param history_id: encoded id string of the new HDA's History
:type payload: dict
:param payload: dictionary structure containing::
- 'from_ld_id': the encoded id of the LibraryDataset to copy
-
+ copy from library:
+ 'source' = 'library'
+ 'content' = [the encoded id from the library dataset]
+
+ copy from url:
+ 'source' = 'url'
+ 'content' = [the url of the dataset]
+
+ copy from file:
+ 'source' = 'upload'
+ 'content' = [the uploaded file content]
:rtype: dict
:returns: dictionary containing detailed information for the new HDA
"""
+
#TODO: copy existing, accessible hda - dataset controller, copy_datasets
#TODO: convert existing, accessible hda - model.DatasetInstance(or hda.datatype).get_converter_types
- from_ld_id = payload.get( 'from_ld_id', None )
+
+ # check parameters
+ source = payload.get('source', None)
+ content = payload.get('content', None)
+ if source not in ['library', 'url', 'upload']:
+ trans.response.status = 400
+ return "history_contents:create() : Please define the source ['library', 'url' or 'upload'] and the content."
+
+ # retrieve history
try:
history = self.get_history( trans, history_id, check_ownership=True, check_accessible=False )
except Exception, e:
- #TODO: no way to tell if it failed bc of perms or other (all MessageExceptions)
+ # no way to tell if it failed bc of perms or other (all MessageExceptions)
trans.response.status = 500
return str( e )
- if from_ld_id:
+ # copy from library dataset
+ if source == 'library':
+
+ # get library data set
try:
- ld = self.get_library_dataset( trans, from_ld_id, check_ownership=False, check_accessible=False )
+ ld = self.get_library_dataset( trans, content, check_ownership=False, check_accessible=False )
assert type( ld ) is trans.app.model.LibraryDataset, (
- "Library content id ( %s ) is not a dataset" % from_ld_id )
-
+ "Library content id ( %s ) is not a dataset" % content )
except AssertionError, e:
trans.response.status = 400
return str( e )
-
except Exception, e:
return str( e )
+ # insert into history
hda = ld.library_dataset_dataset_association.to_history_dataset_association( history, add_to_history=True )
trans.sa_session.flush()
return hda.to_dict()
+ # copy from upload
+ if source == 'upload':
+
+ # get upload specific features
+ dbkey = payload.get('dbkey', None)
+ extension = payload.get('extension', None)
+ space_to_tabs = payload.get('space_to_tabs', False)
+
+ # check for filename
+ if content.filename is None:
+ trans.response.status = 400
+ return "history_contents:create() : The contents parameter needs to contain the uploaded file content."
+
+ # create a dataset
+ dataset = trans.app.model.Dataset()
+ trans.sa_session.add(dataset)
+ trans.sa_session.flush()
+
+ # get file destination
+ file_destination = dataset.get_file_name()
+
+ # save file locally
+ fn = os.path.basename(content.filename)
+ open(file_destination, 'wb').write(content.file.read())
+
+ # log
+ log.info ('The file "' + fn + '" was uploaded successfully.')
+
+ # replace separation with tabs
+ if space_to_tabs:
+ log.info ('Replacing spaces with tabs.')
+ sniff.convert_newlines_sep2tabs(file_destination)
+
+ # guess extension
+ if extension is None:
+ log.info ('Guessing extension.')
+ extension = sniff.guess_ext(file_destination)
+
+ # create hda
+ hda = trans.app.model.HistoryDatasetAssociation(dataset = dataset, name = content.filename,
+ extension = extension, dbkey = dbkey, history = history, sa_session = trans.sa_session)
+
+ # add status ok
+ hda.state = hda.states.OK
+
+ # add dataset to history
+ history.add_dataset(hda, genome_build = dbkey)
+ permissions = trans.app.security_agent.history_get_default_permissions( history )
+ trans.app.security_agent.set_all_dataset_permissions( hda.dataset, permissions )
+
+ # add to session
+ trans.sa_session.add(hda)
+ trans.sa_session.flush()
+
+ # get name
+ return hda.to_dict()
else:
- # TODO: implement other "upload" methods here.
+ # other options
trans.response.status = 501
- return "Not implemented."
+ return
@web.expose_api
def update( self, trans, history_id, id, payload, **kwd ):
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/galaxy.frame.js
--- a/static/scripts/galaxy.frame.js
+++ b/static/scripts/galaxy.frame.js
@@ -3,16 +3,13 @@
*/
// dependencies
-define(["utils/galaxy.css", "libs/backbone/backbone-relational"], function(css) {
+define(["utils/galaxy.css", "galaxy.master", "libs/backbone/backbone-relational"], function(css, mod_master) {
// frame manager
var GalaxyFrameManager = Backbone.View.extend(
{
// base element
- el: '#everything',
-
- // master head
- el_header : '#masthead',
+ el_main: '#everything',
// defaults inputs
options:
@@ -70,9 +67,41 @@
// frame active/disabled
active: false,
+ // button active
+ button_active: null,
+
+ // button load
+ button_load : null,
+
// initialize
initialize : function(options)
{
+ // add to master menu
+ var self = this;
+
+ // add activate icon
+ this.button_active = new mod_master.GalaxyMasterIcon (
+ {
+ icon : 'fa-icon-th',
+ tooltip : 'Enable/Disable Scratchbook',
+ on_click : function(e) { self.event_panel_active(e) }
+ });
+
+ // add to master
+ Galaxy.master.append(this.button_active);
+
+ // add load icon
+ this.button_load = new mod_master.GalaxyMasterIcon (
+ {
+ icon : 'fa-icon-eye-open',
+ tooltip : 'Show/Hide Scratchbook',
+ on_click : function(e) { self.event_panel_load(e) },
+ with_number : true
+ });
+
+ // add to master
+ Galaxy.master.append(this.button_load);
+
// load required css files
css.load_file("static/style/galaxy.frame.css");
@@ -89,8 +118,8 @@
// load menu buttons
$(this.el).append(this.frame_template_menu());
- // load load button
- $(this.el_header).append(this.frame_template_header());
+ // load to main frame
+ $(this.el_main).append($(this.el));
//
// define shadow frame
@@ -117,19 +146,13 @@
// initialize panel
this.panel_refresh();
-
- // link events
- this.event_initialize();
-
- // add
- $(".galaxy-frame-active").tooltip({title: "Enable/Disable Scratchbook"});
- $(".galaxy-frame-load").tooltip({title: "Show/Hide Scratchbook"});
-
+
// catch window resize event
var self = this;
$(window).resize(function ()
{
- self.panel_refresh();
+ if (self.visible)
+ self.panel_refresh();
});
// catch window close
@@ -140,12 +163,6 @@
};
},
- // check for mobile devices
- is_mobile: function()
- {
- return navigator.userAgent.match(/mobile|(iPad)|(iPhone)|(iPod)|(android)|(webOS)/i);
- },
-
/*
EVENT HANDLING
*/
@@ -159,42 +176,22 @@
},
// events
- event_initialize: function()
+ events:
{
- /*if (!this.is_mobile())
- {*/
- this.events = {
- // global page events
- 'mousemove' : 'event_frame_mouse_move',
- 'mouseup' : 'event_frame_mouse_up',
- 'mouseleave' : 'event_frame_mouse_up',
- 'mousewheel' : 'event_panel_scroll',
- 'DOMMouseScroll' : 'event_panel_scroll',
+ // global frame events
+ 'mousemove' : 'event_frame_mouse_move',
+ 'mouseup' : 'event_frame_mouse_up',
+ 'mouseleave' : 'event_frame_mouse_up',
+ 'mousewheel' : 'event_panel_scroll',
+ 'DOMMouseScroll' : 'event_panel_scroll',
- // events fixed to elements
- 'mousedown .galaxy-frame' : 'event_frame_mouse_down',
- 'mousedown .galaxy-frame-active' : 'event_panel_active',
- 'mousedown .galaxy-frame-load' : 'event_panel_load',
- 'mousedown .galaxy-frame-background' : 'event_panel_load',
- 'mousedown .galaxy-frame-scroll-up' : 'event_panel_scroll_up',
- 'mousedown .galaxy-frame-scroll-down' : 'event_panel_scroll_down',
- 'mousedown .f-close' : 'event_frame_close',
- 'mousedown .f-pin' : 'event_frame_lock'
- };
- /*} else {
- this.events = {
- 'touchstart' : 'event_frame_mouse_down',
- 'touchstart .f-close' : 'event_frame_close',
- 'touchstart .f-pin' : 'event_frame_lock',
- 'touchmove' : 'event_frame_mouse_move',
- 'touchend' : 'event_frame_mouse_up',
- 'touchleave' : 'event_mouse_up',
- 'touchstart .galaxy-frame-load' : 'event_frame_load'
- };
- };*/
-
- // delegate
- this.delegateEvents(this.events);
+ // events fixed to elements
+ 'mousedown .galaxy-frame' : 'event_frame_mouse_down',
+ 'mousedown .galaxy-frame-background' : 'event_panel_load',
+ 'mousedown .galaxy-frame-scroll-up' : 'event_panel_scroll_up',
+ 'mousedown .galaxy-frame-scroll-down' : 'event_panel_scroll_down',
+ 'mousedown .f-close' : 'event_frame_close',
+ 'mousedown .f-pin' : 'event_frame_lock'
},
// drag start
@@ -390,7 +387,7 @@
frame.grid_lock = false;
// remove class
- $(frame.id).find('.f-pin').removeClass('f-toggle');
+ $(frame.id).find('.f-pin').removeClass('galaxy-toggle');
$(frame.id).find('.f-header').removeClass('f-not-allowed');
$(frame.id).find('.f-title').removeClass('f-not-allowed');
$(frame.id).find('.f-resize').show();
@@ -400,7 +397,7 @@
frame.grid_lock = true;
// add class
- $(frame.id).find('.f-pin').addClass('f-toggle');
+ $(frame.id).find('.f-pin').addClass('galaxy-toggle');
$(frame.id).find('.f-header').addClass('f-not-allowed');
$(frame.id).find('.f-title').addClass('f-not-allowed');
$(frame.id).find('.f-resize').hide();
@@ -414,9 +411,6 @@
// check
if (this.event.type !== null)
return;
-
- // prevent
- e.preventDefault();
// load panel
this.panel_show_hide();
@@ -428,9 +422,6 @@
// check
if (this.event.type !== null)
return;
-
- // prevent
- e.preventDefault();
// load panel
this.panel_active_disable();
@@ -640,13 +631,13 @@
menu_refresh: function()
{
// update on screen counter
- $(".galaxy-frame-load .number").text(this.frame_counter);
-
+ this.button_load.number(this.frame_counter);
+
// check
if(this.frame_counter == 0)
- $(".galaxy-frame-load").hide();
+ this.button_load.hide();
else
- $(".galaxy-frame-load").show();
+ this.button_load.show();
// scroll up possible?
if (this.top == this.options.top_min)
@@ -733,8 +724,8 @@
$(".galaxy-frame").fadeOut('fast');
// add class
- $(".galaxy-frame-load .icon").addClass("fa-icon-eye-close");
- $(".galaxy-frame-load .icon").removeClass("fa-icon-eye-open");
+ this.button_load.icon("fa-icon-eye-close");
+ this.button_load.untoggle();
// hide background
$(".galaxy-frame-background").hide();
@@ -749,8 +740,8 @@
$(".galaxy-frame").fadeIn('fast');
// add class
- $(".galaxy-frame-load .icon").addClass("fa-icon-eye-open");
- $(".galaxy-frame-load .icon").removeClass("fa-icon-eye-close");
+ this.button_load.icon("fa-icon-eye-open");
+ this.button_load.toggle();
// hide shadow
$(this.galaxy_frame_shadow.id).hide();
@@ -758,8 +749,8 @@
// show background
$(".galaxy-frame-background").show();
- // show menu
- this.menu_refresh();
+ // show panel
+ this.panel_refresh();
}
},
@@ -771,19 +762,19 @@
{
// disable
this.active = false;
-
- // untoggle
- $(".galaxy-frame-active .icon").removeClass("f-toggle");
+ // toggle
+ this.button_active.untoggle();
+
// hide panel
if (this.visible)
this.panel_show_hide();
} else {
// activate
this.active = true;
-
- // toggle
- $(".galaxy-frame-active .icon").addClass("f-toggle");
+
+ // untoggle
+ this.button_active.toggle();
}
},
@@ -1053,23 +1044,23 @@
content = '<iframe scrolling="auto" class="f-iframe" src="' + content + '"></iframe>';
// load template
- return '<div id="' + id + '" class="galaxy-frame f-corner">' +
- '<div class="f-header f-corner">' +
+ return '<div id="' + id + '" class="galaxy-frame galaxy-corner">' +
+ '<div class="f-header galaxy-corner">' +
'<span class="f-title">' + title + '</span>' +
'<span class="f-icon f-pin fa-icon-pushpin"></span>' +
'<span class="f-icon f-close fa-icon-trash"></span>' +
'</div>' +
- '<div class="f-content f-corner">' + content +
+ '<div class="f-content galaxy-corner">' + content +
'<div class="f-cover"></div>' +
'</div>' +
- '<span class="f-resize f-icon f-corner fa-icon-resize-full"></span>' +
+ '<span class="f-resize f-icon galaxy-corner fa-icon-resize-full"></span>' +
'</div>';
},
// fill shadow template
frame_template_shadow: function(id)
{
- return '<div id="' + id + '" class="galaxy-frame-shadow f-corner"></div>';
+ return '<div id="' + id + '" class="galaxy-frame-shadow galaxy-corner"></div>';
},
// fill background template in order to cover underlying iframes
@@ -1078,18 +1069,6 @@
return '<div class="galaxy-frame-background"></div>';
},
- // fill load button template
- frame_template_header: function()
- {
- return '<div class="galaxy-frame-load f-corner">' +
- '<div class="number f-corner">0</div>' +
- '<div class="icon fa-icon-2x"></div>' +
- '</div>' +
- '<div class="galaxy-frame-active f-corner" style="position: absolute; top: 8px;">' +
- '<div class="icon fa-icon-2x fa-icon-th"></div>' +
- '</div>';
- },
-
// fill menu button template
frame_template_menu: function()
{
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/galaxy.master.js
--- /dev/null
+++ b/static/scripts/galaxy.master.js
@@ -0,0 +1,151 @@
+/*
+ galaxy master v1.0
+*/
+
+// dependencies
+define(["utils/galaxy.css", "libs/backbone/backbone-relational"], function(css) {
+
+// master
+var GalaxyMaster = Backbone.View.extend(
+{
+ // base element
+ el_master: '.masthead-inner',
+
+ // initialize
+ initialize : function(options)
+ {
+ // load required css files
+ css.load_file("static/style/galaxy.master.css");
+
+ // define this element
+ this.setElement($(this.template()));
+
+ // append to master
+ $(this.el_master).append($(this.el));
+ },
+
+ // prevent default
+ events:
+ {
+ 'mousedown' : function(e) {e.preventDefault()}
+ },
+
+ // adds and displays a new frame/window
+ append : function(item)
+ {
+ $(this.el).append($(item.el));
+ },
+
+ // adds and displays a new frame/window
+ prepend : function(item)
+ {
+ $(this.el).prepend($(item.el));
+ },
+
+ /*
+ HTML TEMPLATES
+ */
+
+ // fill regular modal template
+ template: function()
+ {
+ return '<div id="galaxy-master" class="galaxy-master"></div>';
+ }
+});
+
+// frame manager
+var GalaxyMasterIcon = Backbone.View.extend(
+{
+ // icon options
+ options:
+ {
+ id : "galaxy-icon",
+ icon : "fa-icon-cog",
+ tooltip : "galaxy-icon",
+ with_number : false,
+ on_click : function() { alert ('clicked') },
+ visible : true
+ },
+
+ // initialize
+ initialize: function (options)
+ {
+ // read in defaults
+ if (options)
+ this.options = _.defaults(options, this.options);
+
+ // add template for icon
+ this.setElement($(this.template(this.options)));
+
+ // configure icon
+ var self = this;
+ $(this.el).find('.icon').tooltip({title: this.options.tooltip})
+ .on('click', self.options.on_click);
+
+ // visiblity
+ if (!this.options.visible)
+ this.hide();
+ },
+
+ // show
+ show: function()
+ {
+ $(this.el).css({visibility : 'visible'});
+ },
+
+ // show
+ hide: function()
+ {
+ $(this.el).css({visibility : 'hidden'});
+ },
+
+ // switch icon
+ icon: function (new_icon)
+ {
+ // update icon class
+ $(this.el).find('.icon').removeClass(this.options.icon)
+ .addClass(new_icon);
+
+ // update icon
+ this.options.icon = new_icon;
+ },
+
+ // toggle
+ toggle: function()
+ {
+ $(this.el).addClass('galaxy-toggle');
+ },
+
+ // untoggle
+ untoggle: function()
+ {
+ $(this.el).removeClass('galaxy-toggle');
+ },
+
+ // set/get number
+ number: function(new_number)
+ {
+ $(this.el).find('.number').text(new_number);
+ },
+
+ // fill template icon
+ template: function (options)
+ {
+ var tmpl = '<div id=' + options.id + ' class="galaxy-icon galaxy-corner">' +
+ '<div class="icon fa-icon-2x ' + options.icon + '"></div>';
+ if (options.with_number)
+ tmpl+= '<div class="number galaxy-corner"></div>';
+ tmpl += '</div>';
+
+ // return template
+ return tmpl;
+ }
+});
+
+// return
+return {
+ GalaxyMaster: GalaxyMaster,
+ GalaxyMasterIcon : GalaxyMasterIcon
+};
+
+});
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/galaxy.modal.js
--- /dev/null
+++ b/static/scripts/galaxy.modal.js
@@ -0,0 +1,122 @@
+/*
+ galaxy modal v1.0
+*/
+
+// dependencies
+define(["utils/galaxy.css", "libs/backbone/backbone-relational"], function(css) {
+
+// frame manager
+var GalaxyModal = Backbone.View.extend(
+{
+ // base element
+ el_main: '#everything',
+
+ // defaults inputs
+ options:
+ {
+ title : "galaxy-modal",
+ body : "No content available."
+ },
+
+ // initialize
+ initialize : function(options)
+ {
+ // load required css files
+ css.load_file("static/style/galaxy.modal.css");
+
+ // read in defaults
+ if (!options)
+ options = this.options;
+ else
+ options = _.defaults(options, this.options);
+
+ // create element
+ this.setElement(this.template(options.title, options.body));
+
+ // append template
+ $(this.el_main).append($(this.el));
+
+ // link elements
+ var footer = (this.$el).find('.footer');
+
+ // append buttons
+ var self = this;
+ if (options.buttons)
+ {
+ // link functions
+ $.each(options.buttons, function(name, value)
+ {
+ footer.append($('<button></button>').text(name).click(value)).append(" ");
+ });
+ } else
+ // default close button
+ footer.append($('<button></button>').text('Close').click(function() { self.hide() })).append(" ");
+
+ // hide
+ $(this.el).hide();
+ },
+
+ /*
+ EVENT HANDLING
+ */
+
+ // event
+ events:
+ {
+ 'mousedown .dialog' : 'event_default',
+ 'mousedown .background' : 'hide'
+ },
+
+ // drag
+ event_default: function (e)
+ {
+ e.preventDefault();
+ },
+
+ // adds and displays a new frame/window
+ show: function()
+ {
+ // fade out
+ this.$el.fadeIn('fast');
+ },
+
+ // hide modal
+ hide: function()
+ {
+ // fade out
+ this.$el.fadeOut('fast');
+ },
+
+ // destroy modal
+ destroy: function ()
+ {
+ // remove element
+ this.$el.remove();
+ },
+
+ /*
+ HTML TEMPLATES
+ */
+
+ // fill regular modal template
+ template: function(title, body)
+ {
+ return '<div class="galaxy-modal">' +
+ '<div class="background"></div>' +
+ '<div class="dialog galaxy-corner">' +
+ '<div class="header">' +
+ '<span><h3 class="title">' + title + '</h3></span>' +
+ '</div>' +
+ '<div class="body">' + body + '</div>' +
+ '<div class="footer"></div>' +
+ '</div>' +
+ '</div>';
+ }
+});
+
+// return
+return {
+ GalaxyModal: GalaxyModal
+};
+
+});
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/galaxy.upload.js
--- /dev/null
+++ b/static/scripts/galaxy.upload.js
@@ -0,0 +1,223 @@
+/*
+ galaxy upload v1.0
+*/
+
+// dependencies
+define(["utils/galaxy.css", "galaxy.modal", "galaxy.master", "utils/galaxy.uploadbox", "libs/backbone/backbone-relational"], function(css, mod_modal, mod_master) {
+
+// galaxy upload
+var GalaxyUpload = Backbone.View.extend(
+{
+ // own modal
+ modal : null,
+
+ // button
+ button_show : null,
+
+ // file counter
+ file_counter: 0,
+
+ // initialize
+ initialize : function()
+ {
+ // load required css files
+ css.load_file("static/style/galaxy.upload.css");
+
+ // add activate icon
+ var self = this;
+ this.button_show = new mod_master.GalaxyMasterIcon (
+ {
+ icon : 'fa-icon-upload',
+ tooltip : 'Upload Files',
+ on_click : function(e) { self.event_show(e) },
+ with_number : true
+ });
+
+ // add to master
+ Galaxy.master.prepend(this.button_show);
+ },
+
+ // events
+ events :
+ {
+ 'mouseover' : 'event_mouseover',
+ 'mouseleave' : 'event_mouseleave'
+ },
+
+ // mouse over
+ event_mouseover : function (e)
+ {
+ $('#galaxy-upload-box').addClass('galaxy-upload-highlight');
+ },
+
+ // mouse left
+ event_mouseleave : function (e)
+ {
+ $('#galaxy-upload-box').removeClass('galaxy-upload-highlight');
+ },
+
+ // start
+ event_start : function(index, file, message)
+ {
+ // make id
+ var id = '#galaxy-upload-file-' + index;
+
+ // add tag
+ $('#galaxy-upload-box').append(this.template_file(id));
+
+ // update title
+ $('#galaxy-upload-file-' + index).find('.title').html(file.name);
+
+ // initialize progress
+ this.event_progress(index, file, 0);
+
+ // update counter
+ this.file_counter++;
+ this.refresh();
+ },
+
+ // progress
+ event_progress : function(index, file, message)
+ {
+ // get progress bar
+ var el = $('#galaxy-upload-file-' + index);
+
+ // get value
+ var percentage = parseInt(message);
+
+ // update progress
+ el.find('.progress').css({ width : percentage + '%' });
+
+ // update info
+ el.find('.info').html(percentage + '% of ' + this.size_to_string (file.size));
+ },
+
+ // end
+ event_success : function(index, file, message)
+ {
+ // update galaxy history
+ Galaxy.currHistoryPanel.refresh();
+
+ // update counter
+ this.file_counter--;
+ this.refresh();
+ },
+
+ // end
+ event_error : function(index, file, message)
+ {
+ // get file box
+ var el = $('#galaxy-upload-file-' + index);
+
+ // update progress frame
+ el.find('.progress-frame').addClass("failed");
+
+ // update error message
+ el.find('.error').html("<strong>Failed:</strong> " + message);
+
+ // update progress
+ this.event_progress(index, file, 0);
+
+ // update counter
+ this.file_counter--;
+ this.refresh();
+ },
+
+ // show/hide upload frame
+ event_show : function (e)
+ {
+ // prevent default
+ e.preventDefault();
+
+ // wait for galaxy history panel (workaround due to the use of iframes)
+ if (!Galaxy.currHistoryPanel)
+ {
+ var self = this;
+ window.setTimeout(function() { self.event_show(e) }, 200)
+ return;
+ }
+
+ // create modal
+ if (!this.modal)
+ {
+ // make modal
+ this.modal = new mod_modal.GalaxyModal(
+ {
+ title : 'Upload files from your local drive',
+ body : this.template()
+ });
+
+ // get current history
+ var current_history = Galaxy.currHistoryPanel.model.get('id');
+
+ // file upload
+ var self = this;
+ $('#galaxy-upload-box').uploadbox(
+ {
+ url : galaxy_config.root + "api/histories/" + current_history + "/contents",
+ dragover : self.event_mouseover,
+ dragleave : self.event_mouseleave,
+ start : function(index, file, message) { self.event_start(index, file, message) },
+ success : function(index, file, message) { self.event_success(index, file, message) },
+ progress : function(index, file, message) { self.event_progress(index, file, message) },
+ error : function(index, file, message) { self.event_error(index, file, message) },
+ data : {source : "upload"}
+ });
+
+ // set element
+ this.setElement('#galaxy-upload-box');
+ }
+
+ // show modal
+ this.modal.show();
+ },
+
+ // update counter
+ refresh: function ()
+ {
+ if (this.file_counter > 0)
+ this.button_show.number(this.file_counter);
+ else
+ this.button_show.number('');
+ },
+
+ // to string
+ size_to_string : function (size)
+ {
+ // identify unit
+ var unit = "";
+ if (size >= 100000000000) { size = size / 100000000000; unit = "TB"; } else
+ if (size >= 100000000) { size = size / 100000000; unit = "GB"; } else
+ if (size >= 100000) { size = size / 100000; unit = "MB"; } else
+ if (size >= 100) { size = size / 100; unit = "KB"; } else
+ { size = size * 10; unit = "b"; }
+ // return formatted string
+ return "<strong>" + (Math.round(size) / 10) + "</strong> " + unit;
+ },
+
+ // load html template
+ template: function()
+ {
+ return '<form id="galaxy-upload-box" class="galaxy-upload-box galaxy-corner"></form>';
+ },
+
+ // load html template
+ template_file: function(id)
+ {
+ return '<div id="' + id.substr(1) + '" class="galaxy-upload-file galaxy-corner-soft galaxy-shadow">' +
+ '<div class="title"></div>' +
+ '<div class="error"></div>' +
+ '<div class="progress-frame galaxy-corner-soft">' +
+ '<div class="progress"></div>' +
+ '</div>' +
+ '<div class="info"></div>' +
+ '</div>';
+ }
+});
+
+// return
+return {
+ GalaxyUpload: GalaxyUpload
+};
+
+});
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/mvc/data.js
--- a/static/scripts/mvc/data.js
+++ b/static/scripts/mvc/data.js
@@ -433,7 +433,7 @@
dataset_params.id = vis_id;
// add widget
- parent.frame_manager.frame_new(
+ parent.Galaxy.frame_manager.frame_new(
{
title : "Trackster",
type : "url",
@@ -450,7 +450,7 @@
var url = vis_url + "/trackster?" + $.param(dataset_params);
// add widget
- parent.frame_manager.frame_new(
+ parent.Galaxy.frame_manager.frame_new(
{
title : "Trackster",
type : "url",
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/mvc/dataset/hda-base.js
--- a/static/scripts/mvc/dataset/hda-base.js
+++ b/static/scripts/mvc/dataset/hda-base.js
@@ -246,7 +246,7 @@
// add frame manager option onclick event
var self = this;
displayBtnData.on_click = function(){
- parent.frame_manager.frame_new({
+ Galaxy.frame_manager.frame_new({
title : "Data Viewer",
type : "url",
location: "center",
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/mvc/dataset/hda-edit.js
--- a/static/scripts/mvc/dataset/hda-edit.js
+++ b/static/scripts/mvc/dataset/hda-edit.js
@@ -289,7 +289,7 @@
return create_scatterplot_action_fn( visualization_url, params );
default:
return function(){// add widget
- parent.frame_manager.frame_new(
+ Galaxy.frame_manager.frame_new(
{
title : "Visualization",
type : "url",
@@ -611,7 +611,7 @@
function create_scatterplot_action_fn( url, params ){
action = function() {
// add widget
- parent.frame_manager.frame_new(
+ Galaxy.frame_manager.frame_new(
{
title : "Scatterplot",
type : "url",
@@ -667,7 +667,7 @@
parent.hide_modal();
// add widget
- parent.frame_manager.frame_new(
+ Galaxy.frame_manager.frame_new(
{
title : "Trackster",
type : "url",
@@ -682,7 +682,7 @@
parent.hide_modal();
// add widget
- parent.frame_manager.frame_new(
+ Galaxy.frame_manager.frame_new(
{
title : "Trackster",
type : "url",
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/mvc/history/history-panel.js
--- a/static/scripts/mvc/history/history-panel.js
+++ b/static/scripts/mvc/history/history-panel.js
@@ -114,6 +114,13 @@
this.urls = {};
},
+ // refresh function
+ refresh : function() {
+ // refresh
+ // TODO: refresh content without reloading frame
+ window.location = window.location;
+ },
+
_setUpEventHandlers : function(){
// ---- model
// don't need to re-render entire model on all changes, just render disk size when it changes
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/packed/galaxy.frame.js
--- a/static/scripts/packed/galaxy.frame.js
+++ b/static/scripts/packed/galaxy.frame.js
@@ -1,1 +1,1 @@
-define(["utils/galaxy.css","libs/backbone/backbone-relational"],function(b){var a=Backbone.View.extend({el:"#everything",el_header:"#masthead",options:{frame:{cols:6,rows:3},rows:1000,cell:130,margin:5,scroll:5,top_min:40,frame_max:10},cols:0,top:0,top_max:0,frame_counter:0,frame_counter_id:0,frame_list:[],galaxy_frame_shadow:null,visible:false,active:false,initialize:function(d){b.load_file("static/style/galaxy.frame.css");if(d){this.options=_.defaults(d,this.options)}this.top=this.top_max=this.options.top_min;$(this.el).append(this.frame_template_background());$(this.el).append(this.frame_template_menu());$(this.el_header).append(this.frame_template_header());var e="#galaxy-frame-shadow";$(this.el).append(this.frame_template_shadow(e.substring(1)));this.galaxy_frame_shadow={id:e,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};this.frame_resize(this.galaxy_frame_shadow,{width:0,height:0});this.frame_list[e]=this.galaxy_frame_shadow;this.panel_refresh();this.event_initialize();$(".galaxy-frame-active").tooltip({title:"Enable/Disable Scratchbook"});$(".galaxy-frame-load").tooltip({title:"Show/Hide Scratchbook"});var c=this;$(window).resize(function(){c.panel_refresh()});window.onbeforeunload=function(){if(c.frame_counter>0){return"You opened "+c.frame_counter+" frame(s) which will be lost."}}},is_mobile:function(){return navigator.userAgent.match(/mobile|(iPad)|(iPhone)|(iPod)|(android)|(webOS)/i)},event:{type:null,target:null,xy:null},event_initialize:function(){this.events={mousemove:"event_frame_mouse_move",mouseup:"event_frame_mouse_up",mouseleave:"event_frame_mouse_up",mousewheel:"event_panel_scroll",DOMMouseScroll:"event_panel_scroll","mousedown .galaxy-frame":"event_frame_mouse_down","mousedown .galaxy-frame-active":"event_panel_active","mousedown .galaxy-frame-load":"event_panel_load","mousedown .galaxy-frame-background":"event_panel_load","mousedown .galaxy-frame-scroll-up":"event_panel_scroll_up","mousedown .galaxy-frame-scroll-down":"event_panel_scroll_down","mousedown .f-close":"event_frame_close","mousedown .f-pin":"event_frame_lock"};this.delegateEvents(this.events)},event_frame_mouse_down:function(c){if(this.event.type!==null){return}if($(c.target).hasClass("f-header")||$(c.target).hasClass("f-title")){this.event.type="drag"}if($(c.target).hasClass("f-resize")){this.event.type="resize"}if(this.event.type===null){return}c.preventDefault();this.event.target=this.event_get_frame(c.target);if(this.event.target.grid_lock){this.event.type=null;return}this.event.xy={x:c.originalEvent.pageX,y:c.originalEvent.pageY};this.frame_drag_start(this.event.target)},event_frame_mouse_move:function(i){if(this.event.type!="drag"&&this.event.type!="resize"){return}var g={x:i.originalEvent.pageX,y:i.originalEvent.pageY};var d={x:g.x-this.event.xy.x,y:g.y-this.event.xy.y};this.event.xy=g;var h=this.frame_screen(this.event.target);if(this.event.type=="resize"){h.width+=d.x;h.height+=d.y;var f=this.options.cell-this.options.margin-1;h.width=Math.max(h.width,f);h.height=Math.max(h.height,f);this.frame_resize(this.event.target,h);h.width=this.to_grid_coord("width",h.width)+1;h.height=this.to_grid_coord("height",h.height)+1;h.width=this.to_pixel_coord("width",h.width);h.height=this.to_pixel_coord("height",h.height);this.frame_resize(this.galaxy_frame_shadow,h);this.frame_insert(this.galaxy_frame_shadow,{top:this.to_grid_coord("top",h.top),left:this.to_grid_coord("left",h.left)})}if(this.event.type=="drag"){h.left+=d.x;h.top+=d.y;this.frame_offset(this.event.target,h);var c={top:this.to_grid_coord("top",h.top),left:this.to_grid_coord("left",h.left)};if(c.left!==0){c.left++}this.frame_insert(this.galaxy_frame_shadow,c)}},event_frame_mouse_up:function(c){if(this.event.type!="drag"&&this.event.type!="resize"){return}this.frame_drag_stop(this.event.target);this.event.type=null},event_frame_close:function(d){if(this.event.type!==null){return}d.preventDefault();var f=this.event_get_frame(d.target);var c=this;$(f.id).fadeOut("fast",function(){$(f.id).remove();delete c.frame_list[f.id];c.frame_counter--;c.panel_refresh(true);c.panel_animation_complete();if(c.visible&&c.frame_counter==0){c.panel_show_hide()}})},event_frame_lock:function(c){if(this.event.type!==null){return}c.preventDefault();var d=this.event_get_frame(c.target);if(d.grid_lock){d.grid_lock=false;$(d.id).find(".f-pin").removeClass("f-toggle");$(d.id).find(".f-header").removeClass("f-not-allowed");$(d.id).find(".f-title").removeClass("f-not-allowed");$(d.id).find(".f-resize").show();$(d.id).find(".f-close").show()}else{d.grid_lock=true;$(d.id).find(".f-pin").addClass("f-toggle");$(d.id).find(".f-header").addClass("f-not-allowed");$(d.id).find(".f-title").addClass("f-not-allowed");$(d.id).find(".f-resize").hide();$(d.id).find(".f-close").hide()}},event_panel_load:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_show_hide()},event_panel_active:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_active_disable()},event_panel_scroll:function(c){if(this.event.type!==null||!this.visible){return}c.preventDefault();var d=c.originalEvent.detail?c.originalEvent.detail:c.originalEvent.wheelDelta/-3;this.panel_scroll(d)},event_panel_scroll_up:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_scroll(-this.options.scroll)},event_panel_scroll_down:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_scroll(this.options.scroll)},event_get_frame:function(c){return this.frame_list["#"+$(c).closest(".galaxy-frame").attr("id")]},frame_drag_start:function(d){this.frame_focus(d,true);var c=this.frame_screen(d);this.frame_resize(this.galaxy_frame_shadow,c);this.frame_grid(this.galaxy_frame_shadow,d.grid_location);d.grid_location=null;$(this.galaxy_frame_shadow.id).show();$(".f-cover").show()},frame_drag_stop:function(d){this.frame_focus(d,false);var c=this.frame_screen(this.galaxy_frame_shadow);this.frame_resize(d,c);this.frame_grid(d,this.galaxy_frame_shadow.grid_location,true);this.galaxy_frame_shadow.grid_location=null;$(this.galaxy_frame_shadow.id).hide();$(".f-cover").hide();this.panel_animation_complete()},to_grid_coord:function(e,d){var c=(e=="width"||e=="height")?1:-1;if(e=="top"){d-=this.top}return parseInt((d+c*this.options.margin)/this.options.cell,10)},to_pixel_coord:function(e,f){var c=(e=="width"||e=="height")?1:-1;var d=(f*this.options.cell)-c*this.options.margin;if(e=="top"){d+=this.top}return d},to_grid:function(c){return{top:this.to_grid_coord("top",c.top),left:this.to_grid_coord("left",c.left),width:this.to_grid_coord("width",c.width),height:this.to_grid_coord("height",c.height)}},to_pixel:function(c){return{top:this.to_pixel_coord("top",c.top),left:this.to_pixel_coord("left",c.left),width:this.to_pixel_coord("width",c.width),height:this.to_pixel_coord("height",c.height)}},is_collision:function(e){function c(h,g){return !(h.left>g.left+g.width-1||h.left+h.width-1<g.left||h.top>g.top+g.height-1||h.top+h.height-1<g.top)}for(var d in this.frame_list){var f=this.frame_list[d];if(f.grid_location===null){continue}if(c(e,f.grid_location)){return true}}return false},location_rank:function(c){return(c.top*this.cols)+c.left},menu_refresh:function(){$(".galaxy-frame-load .number").text(this.frame_counter);if(this.frame_counter==0){$(".galaxy-frame-load").hide()}else{$(".galaxy-frame-load").show()}if(this.top==this.options.top_min){$(".galaxy-frame-scroll-up").hide()}else{$(".galaxy-frame-scroll-up").show()}if(this.top==this.top_max){$(".galaxy-frame-scroll-down").hide()}else{$(".galaxy-frame-scroll-down").show()}},panel_animation_complete:function(){var c=this;$(".galaxy-frame").promise().done(function(){c.panel_scroll(0,true)})},panel_refresh:function(c){this.cols=parseInt($(window).width()/this.options.cell,10)+1;this.frame_insert(null,null,c)},panel_scroll:function(h,c){var e=this.top-this.options.scroll*h;e=Math.max(e,this.top_max);e=Math.min(e,this.options.top_min);if(this.top!=e){for(var d in this.frame_list){var g=this.frame_list[d];if(g.grid_location!==null){var f={top:g.screen_location.top-(this.top-e),left:g.screen_location.left};this.frame_offset(g,f,c)}}this.top=e}this.menu_refresh()},panel_show_hide:function(){if(this.visible){this.visible=false;$(".galaxy-frame").fadeOut("fast");$(".galaxy-frame-load .icon").addClass("fa-icon-eye-close");$(".galaxy-frame-load .icon").removeClass("fa-icon-eye-open");$(".galaxy-frame-background").hide();$(".galaxy-frame-menu").hide()}else{this.visible=true;$(".galaxy-frame").fadeIn("fast");$(".galaxy-frame-load .icon").addClass("fa-icon-eye-open");$(".galaxy-frame-load .icon").removeClass("fa-icon-eye-close");$(this.galaxy_frame_shadow.id).hide();$(".galaxy-frame-background").show();this.menu_refresh()}},panel_active_disable:function(){if(this.active){this.active=false;$(".galaxy-frame-active .icon").removeClass("f-toggle");if(this.visible){this.panel_show_hide()}}else{this.active=true;$(".galaxy-frame-active .icon").addClass("f-toggle")}},frame_new:function(d){if(!this.active){if(d.location=="center"){var c=$(window.parent.document).find("iframe#galaxy_main");c.attr("src",d.content)}else{window.location=d.content}return}if(this.frame_counter>this.options.frame_max){alert("You have reached the maximum number of allowed frames ("+this.options.frame_max+").");return}var e="#galaxy-frame-"+(this.frame_counter_id++);if($(e).length!==0){alert("This frame already exists. This page might contain multiple frame managers.");return}this.top=this.options.top_min;$(this.el).append(this.frame_template(e.substring(1),d.title,d.type,d.content));var f={id:e,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};d.width=this.to_pixel_coord("width",this.options.frame.cols);d.height=this.to_pixel_coord("height",this.options.frame.rows);this.frame_list[e]=f;this.frame_counter++;this.frame_resize(f,{width:d.width,height:d.height});this.frame_insert(f,{top:0,left:0},true);if(!this.visible){this.panel_show_hide()}},frame_insert:function(j,c,e){var d=[];if(j){j.grid_location=null;d.push([j,this.location_rank(c)])}var g=null;for(g in this.frame_list){var h=this.frame_list[g];if(h.grid_location!==null&&!h.grid_lock){h.grid_location=null;d.push([h,h.grid_rank])}}d.sort(function(k,f){var m=k[1];var l=f[1];return m<l?-1:(m>l?1:0)});for(g=0;g<d.length;g++){this.frame_place(d[g][0],e)}this.top_max=0;for(var g in this.frame_list){var j=this.frame_list[g];if(j.grid_location!==null){this.top_max=Math.max(this.top_max,j.grid_location.top+j.grid_location.height)}}this.top_max=$(window).height()-this.top_max*this.options.cell-2*this.options.margin;this.top_max=Math.min(this.top_max,this.options.top_min);this.menu_refresh()},frame_place:function(k,d){k.grid_location=null;var h=this.to_grid(this.frame_screen(k));var c=false;for(var f=0;f<this.options.rows;f++){for(var e=0;e<Math.max(1,this.cols-h.width);e++){h.top=f;h.left=e;if(!this.is_collision(h)){c=true;break}}if(c){break}}if(c){this.frame_grid(k,h,d)}else{console.log("Grid dimensions exceeded.")}},frame_focus:function(e,c){var d=parseInt(b.get_attribute("galaxy-frame","z-index"))+(c?1:0);$(e.id).css("z-index",d)},frame_offset:function(f,e,d){f.screen_location.left=e.left;f.screen_location.top=e.top;if(d){this.frame_focus(f,true);var c=this;$(f.id).animate({top:e.top,left:e.left},"fast",function(){c.frame_focus(f,false)})}else{$(f.id).css({top:e.top,left:e.left})}},frame_resize:function(d,c){$(d.id).css({width:c.width,height:c.height});d.screen_location.width=c.width;d.screen_location.height=c.height},frame_grid:function(e,c,d){e.grid_location=c;this.frame_offset(e,this.to_pixel(c),d);e.grid_rank=this.location_rank(c)},frame_screen:function(d){var c=d.screen_location;return{top:c.top,left:c.left,width:c.width,height:c.height}},frame_template:function(f,e,c,d){if(!e){e=""}if(c=="url"){d='<iframe scrolling="auto" class="f-iframe" src="'+d+'"></iframe>'}return'<div id="'+f+'" class="galaxy-frame f-corner"><div class="f-header f-corner"><span class="f-title">'+e+'</span><span class="f-icon f-pin fa-icon-pushpin"></span><span class="f-icon f-close fa-icon-trash"></span></div><div class="f-content f-corner">'+d+'<div class="f-cover"></div></div><span class="f-resize f-icon f-corner fa-icon-resize-full"></span></div>'},frame_template_shadow:function(c){return'<div id="'+c+'" class="galaxy-frame-shadow f-corner"></div>'},frame_template_background:function(){return'<div class="galaxy-frame-background"></div>'},frame_template_header:function(){return'<div class="galaxy-frame-load f-corner"><div class="number f-corner">0</div><div class="icon fa-icon-2x"></div></div><div class="galaxy-frame-active f-corner" style="position: absolute; top: 8px;"><div class="icon fa-icon-2x fa-icon-th"></div></div>'},frame_template_menu:function(){return'<div class="galaxy-frame-scroll-up galaxy-frame-menu fa-icon-chevron-up fa-icon-2x"></div><div class="galaxy-frame-scroll-down galaxy-frame-menu fa-icon-chevron-down fa-icon-2x"></div>'}});return{GalaxyFrameManager:a}});
\ No newline at end of file
+define(["utils/galaxy.css","galaxy.master","libs/backbone/backbone-relational"],function(b,c){var a=Backbone.View.extend({el_main:"#everything",options:{frame:{cols:6,rows:3},rows:1000,cell:130,margin:5,scroll:5,top_min:40,frame_max:10},cols:0,top:0,top_max:0,frame_counter:0,frame_counter_id:0,frame_list:[],galaxy_frame_shadow:null,visible:false,active:false,button_active:null,button_load:null,initialize:function(e){var d=this;this.button_active=new c.GalaxyMasterIcon({icon:"fa-icon-th",tooltip:"Enable/Disable Scratchbook",on_click:function(g){d.event_panel_active(g)}});Galaxy.master.append(this.button_active);this.button_load=new c.GalaxyMasterIcon({icon:"fa-icon-eye-open",tooltip:"Show/Hide Scratchbook",on_click:function(g){d.event_panel_load(g)},with_number:true});Galaxy.master.append(this.button_load);b.load_file("static/style/galaxy.frame.css");if(e){this.options=_.defaults(e,this.options)}this.top=this.top_max=this.options.top_min;$(this.el).append(this.frame_template_background());$(this.el).append(this.frame_template_menu());$(this.el_main).append($(this.el));var f="#galaxy-frame-shadow";$(this.el).append(this.frame_template_shadow(f.substring(1)));this.galaxy_frame_shadow={id:f,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};this.frame_resize(this.galaxy_frame_shadow,{width:0,height:0});this.frame_list[f]=this.galaxy_frame_shadow;this.panel_refresh();var d=this;$(window).resize(function(){if(d.visible){d.panel_refresh()}});window.onbeforeunload=function(){if(d.frame_counter>0){return"You opened "+d.frame_counter+" frame(s) which will be lost."}}},event:{type:null,target:null,xy:null},events:{mousemove:"event_frame_mouse_move",mouseup:"event_frame_mouse_up",mouseleave:"event_frame_mouse_up",mousewheel:"event_panel_scroll",DOMMouseScroll:"event_panel_scroll","mousedown .galaxy-frame":"event_frame_mouse_down","mousedown .galaxy-frame-background":"event_panel_load","mousedown .galaxy-frame-scroll-up":"event_panel_scroll_up","mousedown .galaxy-frame-scroll-down":"event_panel_scroll_down","mousedown .f-close":"event_frame_close","mousedown .f-pin":"event_frame_lock"},event_frame_mouse_down:function(d){if(this.event.type!==null){return}if($(d.target).hasClass("f-header")||$(d.target).hasClass("f-title")){this.event.type="drag"}if($(d.target).hasClass("f-resize")){this.event.type="resize"}if(this.event.type===null){return}d.preventDefault();this.event.target=this.event_get_frame(d.target);if(this.event.target.grid_lock){this.event.type=null;return}this.event.xy={x:d.originalEvent.pageX,y:d.originalEvent.pageY};this.frame_drag_start(this.event.target)},event_frame_mouse_move:function(j){if(this.event.type!="drag"&&this.event.type!="resize"){return}var h={x:j.originalEvent.pageX,y:j.originalEvent.pageY};var f={x:h.x-this.event.xy.x,y:h.y-this.event.xy.y};this.event.xy=h;var i=this.frame_screen(this.event.target);if(this.event.type=="resize"){i.width+=f.x;i.height+=f.y;var g=this.options.cell-this.options.margin-1;i.width=Math.max(i.width,g);i.height=Math.max(i.height,g);this.frame_resize(this.event.target,i);i.width=this.to_grid_coord("width",i.width)+1;i.height=this.to_grid_coord("height",i.height)+1;i.width=this.to_pixel_coord("width",i.width);i.height=this.to_pixel_coord("height",i.height);this.frame_resize(this.galaxy_frame_shadow,i);this.frame_insert(this.galaxy_frame_shadow,{top:this.to_grid_coord("top",i.top),left:this.to_grid_coord("left",i.left)})}if(this.event.type=="drag"){i.left+=f.x;i.top+=f.y;this.frame_offset(this.event.target,i);var d={top:this.to_grid_coord("top",i.top),left:this.to_grid_coord("left",i.left)};if(d.left!==0){d.left++}this.frame_insert(this.galaxy_frame_shadow,d)}},event_frame_mouse_up:function(d){if(this.event.type!="drag"&&this.event.type!="resize"){return}this.frame_drag_stop(this.event.target);this.event.type=null},event_frame_close:function(f){if(this.event.type!==null){return}f.preventDefault();var g=this.event_get_frame(f.target);var d=this;$(g.id).fadeOut("fast",function(){$(g.id).remove();delete d.frame_list[g.id];d.frame_counter--;d.panel_refresh(true);d.panel_animation_complete();if(d.visible&&d.frame_counter==0){d.panel_show_hide()}})},event_frame_lock:function(d){if(this.event.type!==null){return}d.preventDefault();var f=this.event_get_frame(d.target);if(f.grid_lock){f.grid_lock=false;$(f.id).find(".f-pin").removeClass("galaxy-toggle");$(f.id).find(".f-header").removeClass("f-not-allowed");$(f.id).find(".f-title").removeClass("f-not-allowed");$(f.id).find(".f-resize").show();$(f.id).find(".f-close").show()}else{f.grid_lock=true;$(f.id).find(".f-pin").addClass("galaxy-toggle");$(f.id).find(".f-header").addClass("f-not-allowed");$(f.id).find(".f-title").addClass("f-not-allowed");$(f.id).find(".f-resize").hide();$(f.id).find(".f-close").hide()}},event_panel_load:function(d){if(this.event.type!==null){return}this.panel_show_hide()},event_panel_active:function(d){if(this.event.type!==null){return}this.panel_active_disable()},event_panel_scroll:function(d){if(this.event.type!==null||!this.visible){return}d.preventDefault();var f=d.originalEvent.detail?d.originalEvent.detail:d.originalEvent.wheelDelta/-3;this.panel_scroll(f)},event_panel_scroll_up:function(d){if(this.event.type!==null){return}d.preventDefault();this.panel_scroll(-this.options.scroll)},event_panel_scroll_down:function(d){if(this.event.type!==null){return}d.preventDefault();this.panel_scroll(this.options.scroll)},event_get_frame:function(d){return this.frame_list["#"+$(d).closest(".galaxy-frame").attr("id")]},frame_drag_start:function(e){this.frame_focus(e,true);var d=this.frame_screen(e);this.frame_resize(this.galaxy_frame_shadow,d);this.frame_grid(this.galaxy_frame_shadow,e.grid_location);e.grid_location=null;$(this.galaxy_frame_shadow.id).show();$(".f-cover").show()},frame_drag_stop:function(e){this.frame_focus(e,false);var d=this.frame_screen(this.galaxy_frame_shadow);this.frame_resize(e,d);this.frame_grid(e,this.galaxy_frame_shadow.grid_location,true);this.galaxy_frame_shadow.grid_location=null;$(this.galaxy_frame_shadow.id).hide();$(".f-cover").hide();this.panel_animation_complete()},to_grid_coord:function(f,e){var d=(f=="width"||f=="height")?1:-1;if(f=="top"){e-=this.top}return parseInt((e+d*this.options.margin)/this.options.cell,10)},to_pixel_coord:function(f,h){var d=(f=="width"||f=="height")?1:-1;var e=(h*this.options.cell)-d*this.options.margin;if(f=="top"){e+=this.top}return e},to_grid:function(d){return{top:this.to_grid_coord("top",d.top),left:this.to_grid_coord("left",d.left),width:this.to_grid_coord("width",d.width),height:this.to_grid_coord("height",d.height)}},to_pixel:function(d){return{top:this.to_pixel_coord("top",d.top),left:this.to_pixel_coord("left",d.left),width:this.to_pixel_coord("width",d.width),height:this.to_pixel_coord("height",d.height)}},is_collision:function(f){function d(i,g){return !(i.left>g.left+g.width-1||i.left+i.width-1<g.left||i.top>g.top+g.height-1||i.top+i.height-1<g.top)}for(var e in this.frame_list){var h=this.frame_list[e];if(h.grid_location===null){continue}if(d(f,h.grid_location)){return true}}return false},location_rank:function(d){return(d.top*this.cols)+d.left},menu_refresh:function(){this.button_load.number(this.frame_counter);if(this.frame_counter==0){this.button_load.hide()}else{this.button_load.show()}if(this.top==this.options.top_min){$(".galaxy-frame-scroll-up").hide()}else{$(".galaxy-frame-scroll-up").show()}if(this.top==this.top_max){$(".galaxy-frame-scroll-down").hide()}else{$(".galaxy-frame-scroll-down").show()}},panel_animation_complete:function(){var d=this;$(".galaxy-frame").promise().done(function(){d.panel_scroll(0,true)})},panel_refresh:function(d){this.cols=parseInt($(window).width()/this.options.cell,10)+1;this.frame_insert(null,null,d)},panel_scroll:function(j,d){var f=this.top-this.options.scroll*j;f=Math.max(f,this.top_max);f=Math.min(f,this.options.top_min);if(this.top!=f){for(var e in this.frame_list){var h=this.frame_list[e];if(h.grid_location!==null){var g={top:h.screen_location.top-(this.top-f),left:h.screen_location.left};this.frame_offset(h,g,d)}}this.top=f}this.menu_refresh()},panel_show_hide:function(){if(this.visible){this.visible=false;$(".galaxy-frame").fadeOut("fast");this.button_load.icon("fa-icon-eye-close");this.button_load.untoggle();$(".galaxy-frame-background").hide();$(".galaxy-frame-menu").hide()}else{this.visible=true;$(".galaxy-frame").fadeIn("fast");this.button_load.icon("fa-icon-eye-open");this.button_load.toggle();$(this.galaxy_frame_shadow.id).hide();$(".galaxy-frame-background").show();this.panel_refresh()}},panel_active_disable:function(){if(this.active){this.active=false;this.button_active.untoggle();if(this.visible){this.panel_show_hide()}}else{this.active=true;this.button_active.toggle()}},frame_new:function(e){if(!this.active){if(e.location=="center"){var d=$(window.parent.document).find("iframe#galaxy_main");d.attr("src",e.content)}else{window.location=e.content}return}if(this.frame_counter>this.options.frame_max){alert("You have reached the maximum number of allowed frames ("+this.options.frame_max+").");return}var f="#galaxy-frame-"+(this.frame_counter_id++);if($(f).length!==0){alert("This frame already exists. This page might contain multiple frame managers.");return}this.top=this.options.top_min;$(this.el).append(this.frame_template(f.substring(1),e.title,e.type,e.content));var g={id:f,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};e.width=this.to_pixel_coord("width",this.options.frame.cols);e.height=this.to_pixel_coord("height",this.options.frame.rows);this.frame_list[f]=g;this.frame_counter++;this.frame_resize(g,{width:e.width,height:e.height});this.frame_insert(g,{top:0,left:0},true);if(!this.visible){this.panel_show_hide()}},frame_insert:function(k,d,g){var e=[];if(k){k.grid_location=null;e.push([k,this.location_rank(d)])}var h=null;for(h in this.frame_list){var j=this.frame_list[h];if(j.grid_location!==null&&!j.grid_lock){j.grid_location=null;e.push([j,j.grid_rank])}}e.sort(function(l,f){var n=l[1];var m=f[1];return n<m?-1:(n>m?1:0)});for(h=0;h<e.length;h++){this.frame_place(e[h][0],g)}this.top_max=0;for(var h in this.frame_list){var k=this.frame_list[h];if(k.grid_location!==null){this.top_max=Math.max(this.top_max,k.grid_location.top+k.grid_location.height)}}this.top_max=$(window).height()-this.top_max*this.options.cell-2*this.options.margin;this.top_max=Math.min(this.top_max,this.options.top_min);this.menu_refresh()},frame_place:function(l,e){l.grid_location=null;var k=this.to_grid(this.frame_screen(l));var d=false;for(var h=0;h<this.options.rows;h++){for(var f=0;f<Math.max(1,this.cols-k.width);f++){k.top=h;k.left=f;if(!this.is_collision(k)){d=true;break}}if(d){break}}if(d){this.frame_grid(l,k,e)}else{console.log("Grid dimensions exceeded.")}},frame_focus:function(f,d){var e=parseInt(b.get_attribute("galaxy-frame","z-index"))+(d?1:0);$(f.id).css("z-index",e)},frame_offset:function(g,f,e){g.screen_location.left=f.left;g.screen_location.top=f.top;if(e){this.frame_focus(g,true);var d=this;$(g.id).animate({top:f.top,left:f.left},"fast",function(){d.frame_focus(g,false)})}else{$(g.id).css({top:f.top,left:f.left})}},frame_resize:function(e,d){$(e.id).css({width:d.width,height:d.height});e.screen_location.width=d.width;e.screen_location.height=d.height},frame_grid:function(f,d,e){f.grid_location=d;this.frame_offset(f,this.to_pixel(d),e);f.grid_rank=this.location_rank(d)},frame_screen:function(e){var d=e.screen_location;return{top:d.top,left:d.left,width:d.width,height:d.height}},frame_template:function(g,f,d,e){if(!f){f=""}if(d=="url"){e='<iframe scrolling="auto" class="f-iframe" src="'+e+'"></iframe>'}return'<div id="'+g+'" class="galaxy-frame galaxy-corner"><div class="f-header galaxy-corner"><span class="f-title">'+f+'</span><span class="f-icon f-pin fa-icon-pushpin"></span><span class="f-icon f-close fa-icon-trash"></span></div><div class="f-content galaxy-corner">'+e+'<div class="f-cover"></div></div><span class="f-resize f-icon galaxy-corner fa-icon-resize-full"></span></div>'},frame_template_shadow:function(d){return'<div id="'+d+'" class="galaxy-frame-shadow galaxy-corner"></div>'},frame_template_background:function(){return'<div class="galaxy-frame-background"></div>'},frame_template_menu:function(){return'<div class="galaxy-frame-scroll-up galaxy-frame-menu fa-icon-chevron-up fa-icon-2x"></div><div class="galaxy-frame-scroll-down galaxy-frame-menu fa-icon-chevron-down fa-icon-2x"></div>'}});return{GalaxyFrameManager:a}});
\ No newline at end of file
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/packed/galaxy.master.js
--- /dev/null
+++ b/static/scripts/packed/galaxy.master.js
@@ -0,0 +1,1 @@
+define(["utils/galaxy.css","libs/backbone/backbone-relational"],function(b){var a=Backbone.View.extend({el_master:".masthead-inner",initialize:function(d){b.load_file("static/style/galaxy.master.css");this.setElement($(this.template()));$(this.el_master).append($(this.el))},events:{mousedown:function(d){d.preventDefault()}},append:function(d){$(this.el).append($(d.el))},prepend:function(d){$(this.el).prepend($(d.el))},template:function(){return'<div id="galaxy-master" class="galaxy-master"></div>'}});var c=Backbone.View.extend({options:{id:"galaxy-icon",icon:"fa-icon-cog",tooltip:"galaxy-icon",with_number:false,on_click:function(){alert("clicked")},visible:true},initialize:function(e){if(e){this.options=_.defaults(e,this.options)}this.setElement($(this.template(this.options)));var d=this;$(this.el).find(".icon").tooltip({title:this.options.tooltip}).on("click",d.options.on_click);if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},icon:function(d){$(this.el).find(".icon").removeClass(this.options.icon).addClass(d);this.options.icon=d},toggle:function(){$(this.el).addClass("galaxy-toggle")},untoggle:function(){$(this.el).removeClass("galaxy-toggle")},number:function(d){$(this.el).find(".number").text(d)},template:function(e){var d="<div id="+e.id+' class="galaxy-icon galaxy-corner"><div class="icon fa-icon-2x '+e.icon+'"></div>';if(e.with_number){d+='<div class="number galaxy-corner"></div>'}d+="</div>";return d}});return{GalaxyMaster:a,GalaxyMasterIcon:c}});
\ No newline at end of file
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/packed/galaxy.modal.js
--- /dev/null
+++ b/static/scripts/packed/galaxy.modal.js
@@ -0,0 +1,1 @@
+define(["utils/galaxy.css","libs/backbone/backbone-relational"],function(a){var b=Backbone.View.extend({el_main:"#everything",options:{title:"galaxy-modal",body:"No content available."},initialize:function(d){a.load_file("static/style/galaxy.modal.css");if(!d){d=this.options}else{d=_.defaults(d,this.options)}this.setElement(this.template(d.title,d.body));$(this.el_main).append($(this.el));var e=(this.$el).find(".footer");var c=this;if(d.buttons){$.each(d.buttons,function(f,g){e.append($("<button></button>").text(f).click(g)).append(" ")})}else{e.append($("<button></button>").text("Close").click(function(){c.hide()})).append(" ")}$(this.el).hide()},events:{"mousedown .dialog":"event_default","mousedown .background":"hide"},event_default:function(c){c.preventDefault()},show:function(){this.$el.fadeIn("fast")},hide:function(){this.$el.fadeOut("fast")},destroy:function(){this.$el.remove()},template:function(d,c){return'<div class="galaxy-modal"><div class="background"></div><div class="dialog galaxy-corner"><div class="header"><span><h3 class="title">'+d+'</h3></span></div><div class="body">'+c+'</div><div class="footer"></div></div></div>'}});return{GalaxyModal:b}});
\ No newline at end of file
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/packed/galaxy.upload.js
--- /dev/null
+++ b/static/scripts/packed/galaxy.upload.js
@@ -0,0 +1,1 @@
+define(["utils/galaxy.css","galaxy.modal","galaxy.master","utils/galaxy.uploadbox","libs/backbone/backbone-relational"],function(c,b,d){var a=Backbone.View.extend({modal:null,button_show:null,file_counter:0,initialize:function(){c.load_file("static/style/galaxy.upload.css");var e=this;this.button_show=new d.GalaxyMasterIcon({icon:"fa-icon-upload",tooltip:"Upload Files",on_click:function(f){e.event_show(f)},with_number:true});Galaxy.master.prepend(this.button_show)},events:{mouseover:"event_mouseover",mouseleave:"event_mouseleave"},event_mouseover:function(f){$("#galaxy-upload-box").addClass("galaxy-upload-highlight")},event_mouseleave:function(f){$("#galaxy-upload-box").removeClass("galaxy-upload-highlight")},event_start:function(e,f,g){var h="#galaxy-upload-file-"+e;$("#galaxy-upload-box").append(this.template_file(h));$("#galaxy-upload-file-"+e).find(".title").html(f.name);this.event_progress(e,f,0);this.file_counter++;this.refresh()},event_progress:function(f,g,i){var h=$("#galaxy-upload-file-"+f);var e=parseInt(i);h.find(".progress").css({width:e+"%"});h.find(".info").html(e+"% of "+this.size_to_string(g.size))},event_success:function(e,f,g){Galaxy.currHistoryPanel.refresh();this.file_counter--;this.refresh()},event_error:function(e,f,h){var g=$("#galaxy-upload-file-"+e);g.find(".progress-frame").addClass("failed");g.find(".error").html("<strong>Failed:</strong> "+h);this.event_progress(e,f,0);this.file_counter--;this.refresh()},event_show:function(h){h.preventDefault();if(!Galaxy.currHistoryPanel){var g=this;window.setTimeout(function(){g.event_show(h)},200);return}if(!this.modal){this.modal=new b.GalaxyModal({title:"Upload files from your local drive",body:this.template()});var f=Galaxy.currHistoryPanel.model.get("id");var g=this;$("#galaxy-upload-box").uploadbox({url:galaxy_config.root+"api/histories/"+f+"/contents",dragover:g.event_mouseover,dragleave:g.event_mouseleave,start:function(e,i,j){g.event_start(e,i,j)},success:function(e,i,j){g.event_success(e,i,j)},progress:function(e,i,j){g.event_progress(e,i,j)},error:function(e,i,j){g.event_error(e,i,j)},data:{source:"upload"}});this.setElement("#galaxy-upload-box")}this.modal.show()},refresh:function(){if(this.file_counter>0){this.button_show.number(this.file_counter)}else{this.button_show.number("")}},size_to_string:function(e){var f="";if(e>=100000000000){e=e/100000000000;f="TB"}else{if(e>=100000000){e=e/100000000;f="GB"}else{if(e>=100000){e=e/100000;f="MB"}else{if(e>=100){e=e/100;f="KB"}else{e=e*10;f="b"}}}}return"<strong>"+(Math.round(e)/10)+"</strong> "+f},template:function(){return'<form id="galaxy-upload-box" class="galaxy-upload-box galaxy-corner"></form>'},template_file:function(e){return'<div id="'+e.substr(1)+'" class="galaxy-upload-file galaxy-corner-soft galaxy-shadow"><div class="title"></div><div class="error"></div><div class="progress-frame galaxy-corner-soft"><div class="progress"></div></div><div class="info"></div></div>'}});return{GalaxyUpload:a}});
\ No newline at end of file
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/packed/mvc/data.js
--- a/static/scripts/packed/mvc/data.js
+++ b/static/scripts/packed/mvc/data.js
@@ -1,1 +1,1 @@
-define(["libs/backbone/backbone-relational"],function(){var d=Backbone.RelationalModel.extend({});var e=Backbone.RelationalModel.extend({defaults:{id:"",type:"",name:"",hda_ldda:"hda",metadata:null},initialize:function(){this.on("change",this._set_metadata,this)},_set_metadata:function(){var i=new d();_.each(_.keys(this.attributes),function(j){if(j.indexOf("metadata_")===0){var l=j.split("metadata_")[1];i.set(l,this.attributes[j]);delete this.attributes[j]}},this);this.set("metadata",i,{silent:true})},get_metadata:function(i){return this.attributes.metadata.get(i)},urlRoot:galaxy_config.root+"api/datasets"});var c=e.extend({defaults:_.extend({},e.prototype.defaults,{chunk_url:null,first_data_chunk:null,chunk_index:-1,at_eof:false}),initialize:function(i){e.prototype.initialize.call(this);this.attributes.chunk_index=(this.attributes.first_data_chunk?1:0)},get_next_chunk:function(){if(this.attributes.at_eof){return null}var i=this,j=$.Deferred();$.getJSON(this.attributes.chunk_url,{chunk:i.attributes.chunk_index++}).success(function(k){var l;if(k.ck_data!==""){l=k}else{i.attributes.at_eof=true;l=null}j.resolve(l)});return j}});var g=Backbone.Collection.extend({model:e});var f=Backbone.View.extend({initialize:function(i){new b(i)},render:function(){var m=$("<table/>").attr({id:"content_table",cellpadding:0});this.$el.append(m);var i=this.model.get_metadata("column_names");if(i){m.append("<tr><th>"+i.join("</th><th>")+"</th></tr>")}var k=this.model.get("first_data_chunk");if(k){this._renderChunk(k)}var j=this,n=_.find(this.$el.parents(),function(o){return $(o).css("overflow")==="auto"}),l=false;if(!n){n=window}n=$(n);n.scroll(function(){if(!l&&(j.$el.height()-n.scrollTop()-n.height()<=0)){l=true;$.when(j.model.get_next_chunk()).then(function(o){if(o){j._renderChunk(o);l=false}})}});$("#loading_indicator").ajaxStart(function(){$(this).show()}).ajaxStop(function(){$(this).hide()})},_renderCell:function(k,i,l){var j=this.model.get_metadata("column_types");if(l!==undefined){return $("<td>").attr("colspan",l).addClass("stringalign").text(k)}else{if(j[i]==="str"||j==="list"){return $("<td>").addClass("stringalign").text(k)}else{return $("<td>").text(k)}}},_renderRow:function(i){var j=i.split("\t"),l=$("<tr>"),k=this.model.get_metadata("columns");if(j.length===k){_.each(j,function(n,m){l.append(this._renderCell(n,m))},this)}else{if(j.length>k){_.each(j.slice(0,k-1),function(n,m){l.append(this._renderCell(n,m))},this);l.append(this._renderCell(j.slice(k-1).join("\t"),k-1))}else{if(k>5&&j.length===k-1){_.each(j,function(n,m){l.append(this._renderCell(n,m))},this);l.append($("<td>"))}else{l.append(this._renderCell(i,0,k))}}}return l},_renderChunk:function(i){var j=this.$el.find("table");_.each(i.ck_data.split("\n"),function(k,l){j.append(this._renderRow(k))},this)}});var b=Backbone.View.extend({col:{chrom:null,start:null,end:null},url_viz:null,dataset_id:null,genome_build:null,data_type:null,initialize:function(k){var j=k.model.attributes;var m=k.model.attributes.metadata.attributes;if(typeof j.data_type!=="undefined"){this.data_type=j.data_type}else{console.log("TabularButtonTrackster : Data type missing.")}if(this.data_type=="bed"){if(typeof m.chromCol!=="undefined"||typeof m.startCol!=="undefined"||typeof m.endCol!=="undefined"){this.col.chrom=m.chromCol-1;this.col.start=m.startCol-1;this.col.end=m.endCol-1}else{console.log("TabularButtonTrackster : Bed-file metadata incomplete.")}}if(this.data_type=="vcf"){function l(o,p){for(var n=0;n<p.length;n++){if(p[n].match(o)){return n}}return -1}this.col.chrom=l("Chrom",m.column_names);this.col.start=l("Pos",m.column_names);this.col.end=null;if(this.col.chrom==-1||this.col.start==-1){console.log("TabularButtonTrackster : VCF-file metadata incomplete.")}}if(this.col.chrom===null){console.log("TabularButtonTrackster : Chromosome column undefined.");return}if(typeof k.model.attributes.id==="undefined"){console.log("TabularButtonTrackster : Dataset identification is missing.")}else{this.dataset_id=k.model.attributes.id}if(typeof k.model.attributes.url_viz==="undefined"){console.log("TabularButtonTrackster : Url for visualization controller is missing.")}else{this.url_viz=k.model.attributes.url_viz}if(typeof k.model.attributes.genome_build!=="undefined"){this.genome_build=k.model.attributes.genome_build}var i=new IconButtonView({model:new IconButton({title:"Visualize",icon_class:"chart_curve",id:"btn_viz"})});this.$el.append(i.render().$el);$("#btn_viz").hide()},events:{"mouseover tr":"btn_viz_show",mouseleave:"btn_viz_hide"},btn_viz_show:function(n){function m(s){return !isNaN(parseFloat(s))&&isFinite(s)}if(this.col.chrom===null){return}var r=$(n.target).parent();var o=r.children().eq(this.col.chrom).html();var i=r.children().eq(this.col.start).html();var k=this.col.end?r.children().eq(this.col.end).html():i;if(!o.match("^#")&&o!==""&&m(i)){var q={dataset_id:this.dataset_id,gene_region:o+":"+i+"-"+k};var l=r.offset();var j=l.left-10;var p=l.top-$(window).scrollTop();$("#btn_viz").css({position:"fixed",top:p+"px",left:j+"px"});$("#btn_viz").off("click");$("#btn_viz").click(this.create_trackster_action(this.url_viz,q,this.genome_build));$("#btn_viz").show()}else{$("#btn_viz").hide()}},btn_viz_hide:function(){$("#btn_viz").hide()},create_trackster_action:function(i,k,j){return function(){var l={};if(j){l["f-dbkey"]=j}$.ajax({url:i+"/list_tracks?"+$.param(l),dataType:"html",error:function(){alert(("Could not add this dataset to browser")+".")},success:function(m){var n=window.parent;n.show_modal(("View Data in a New or Saved Visualization"),"",{Cancel:function(){n.hide_modal()},"View in saved visualization":function(){n.show_modal(("Add Data to Saved Visualization"),m,{Cancel:function(){n.hide_modal()},"Add to visualization":function(){$(n.document).find("input[name=id]:checked").each(function(){var o=$(this).val();k.id=o;n.frame_manager.frame_new({title:"Trackster",type:"url",content:i+"/trackster?"+$.param(k)});n.hide_modal()})}})},"View in new visualization":function(){var o=i+"/trackster?"+$.param(k);n.frame_manager.frame_new({title:"Trackster",type:"url",content:o});n.hide_modal()}})}});return false}}});var a=function(l,j,m,i){var k=new j({model:new l(m)});k.render();if(i){i.append(k.$el)}return k};var h=function(k,i){var j=$("<div/>").appendTo(i);return new f({el:j,model:new c(k)}).render()};return{Dataset:e,TabularDataset:c,DatasetCollection:g,TabularDatasetChunkedView:f,createTabularDatasetChunkedView:h}});
\ No newline at end of file
+define(["libs/backbone/backbone-relational"],function(){var d=Backbone.RelationalModel.extend({});var e=Backbone.RelationalModel.extend({defaults:{id:"",type:"",name:"",hda_ldda:"hda",metadata:null},initialize:function(){this.on("change",this._set_metadata,this)},_set_metadata:function(){var i=new d();_.each(_.keys(this.attributes),function(j){if(j.indexOf("metadata_")===0){var l=j.split("metadata_")[1];i.set(l,this.attributes[j]);delete this.attributes[j]}},this);this.set("metadata",i,{silent:true})},get_metadata:function(i){return this.attributes.metadata.get(i)},urlRoot:galaxy_config.root+"api/datasets"});var c=e.extend({defaults:_.extend({},e.prototype.defaults,{chunk_url:null,first_data_chunk:null,chunk_index:-1,at_eof:false}),initialize:function(i){e.prototype.initialize.call(this);this.attributes.chunk_index=(this.attributes.first_data_chunk?1:0)},get_next_chunk:function(){if(this.attributes.at_eof){return null}var i=this,j=$.Deferred();$.getJSON(this.attributes.chunk_url,{chunk:i.attributes.chunk_index++}).success(function(k){var l;if(k.ck_data!==""){l=k}else{i.attributes.at_eof=true;l=null}j.resolve(l)});return j}});var g=Backbone.Collection.extend({model:e});var f=Backbone.View.extend({initialize:function(i){new b(i)},render:function(){var m=$("<table/>").attr({id:"content_table",cellpadding:0});this.$el.append(m);var i=this.model.get_metadata("column_names");if(i){m.append("<tr><th>"+i.join("</th><th>")+"</th></tr>")}var k=this.model.get("first_data_chunk");if(k){this._renderChunk(k)}var j=this,n=_.find(this.$el.parents(),function(o){return $(o).css("overflow")==="auto"}),l=false;if(!n){n=window}n=$(n);n.scroll(function(){if(!l&&(j.$el.height()-n.scrollTop()-n.height()<=0)){l=true;$.when(j.model.get_next_chunk()).then(function(o){if(o){j._renderChunk(o);l=false}})}});$("#loading_indicator").ajaxStart(function(){$(this).show()}).ajaxStop(function(){$(this).hide()})},_renderCell:function(k,i,l){var j=this.model.get_metadata("column_types");if(l!==undefined){return $("<td>").attr("colspan",l).addClass("stringalign").text(k)}else{if(j[i]==="str"||j==="list"){return $("<td>").addClass("stringalign").text(k)}else{return $("<td>").text(k)}}},_renderRow:function(i){var j=i.split("\t"),l=$("<tr>"),k=this.model.get_metadata("columns");if(j.length===k){_.each(j,function(n,m){l.append(this._renderCell(n,m))},this)}else{if(j.length>k){_.each(j.slice(0,k-1),function(n,m){l.append(this._renderCell(n,m))},this);l.append(this._renderCell(j.slice(k-1).join("\t"),k-1))}else{if(k>5&&j.length===k-1){_.each(j,function(n,m){l.append(this._renderCell(n,m))},this);l.append($("<td>"))}else{l.append(this._renderCell(i,0,k))}}}return l},_renderChunk:function(i){var j=this.$el.find("table");_.each(i.ck_data.split("\n"),function(k,l){j.append(this._renderRow(k))},this)}});var b=Backbone.View.extend({col:{chrom:null,start:null,end:null},url_viz:null,dataset_id:null,genome_build:null,data_type:null,initialize:function(k){var j=k.model.attributes;var m=k.model.attributes.metadata.attributes;if(typeof j.data_type!=="undefined"){this.data_type=j.data_type}else{console.log("TabularButtonTrackster : Data type missing.")}if(this.data_type=="bed"){if(typeof m.chromCol!=="undefined"||typeof m.startCol!=="undefined"||typeof m.endCol!=="undefined"){this.col.chrom=m.chromCol-1;this.col.start=m.startCol-1;this.col.end=m.endCol-1}else{console.log("TabularButtonTrackster : Bed-file metadata incomplete.")}}if(this.data_type=="vcf"){function l(o,p){for(var n=0;n<p.length;n++){if(p[n].match(o)){return n}}return -1}this.col.chrom=l("Chrom",m.column_names);this.col.start=l("Pos",m.column_names);this.col.end=null;if(this.col.chrom==-1||this.col.start==-1){console.log("TabularButtonTrackster : VCF-file metadata incomplete.")}}if(this.col.chrom===null){console.log("TabularButtonTrackster : Chromosome column undefined.");return}if(typeof k.model.attributes.id==="undefined"){console.log("TabularButtonTrackster : Dataset identification is missing.")}else{this.dataset_id=k.model.attributes.id}if(typeof k.model.attributes.url_viz==="undefined"){console.log("TabularButtonTrackster : Url for visualization controller is missing.")}else{this.url_viz=k.model.attributes.url_viz}if(typeof k.model.attributes.genome_build!=="undefined"){this.genome_build=k.model.attributes.genome_build}var i=new IconButtonView({model:new IconButton({title:"Visualize",icon_class:"chart_curve",id:"btn_viz"})});this.$el.append(i.render().$el);$("#btn_viz").hide()},events:{"mouseover tr":"btn_viz_show",mouseleave:"btn_viz_hide"},btn_viz_show:function(n){function m(s){return !isNaN(parseFloat(s))&&isFinite(s)}if(this.col.chrom===null){return}var r=$(n.target).parent();var o=r.children().eq(this.col.chrom).html();var i=r.children().eq(this.col.start).html();var k=this.col.end?r.children().eq(this.col.end).html():i;if(!o.match("^#")&&o!==""&&m(i)){var q={dataset_id:this.dataset_id,gene_region:o+":"+i+"-"+k};var l=r.offset();var j=l.left-10;var p=l.top-$(window).scrollTop();$("#btn_viz").css({position:"fixed",top:p+"px",left:j+"px"});$("#btn_viz").off("click");$("#btn_viz").click(this.create_trackster_action(this.url_viz,q,this.genome_build));$("#btn_viz").show()}else{$("#btn_viz").hide()}},btn_viz_hide:function(){$("#btn_viz").hide()},create_trackster_action:function(i,k,j){return function(){var l={};if(j){l["f-dbkey"]=j}$.ajax({url:i+"/list_tracks?"+$.param(l),dataType:"html",error:function(){alert(("Could not add this dataset to browser")+".")},success:function(m){var n=window.parent;n.show_modal(("View Data in a New or Saved Visualization"),"",{Cancel:function(){n.hide_modal()},"View in saved visualization":function(){n.show_modal(("Add Data to Saved Visualization"),m,{Cancel:function(){n.hide_modal()},"Add to visualization":function(){$(n.document).find("input[name=id]:checked").each(function(){var o=$(this).val();k.id=o;n.Galaxy.frame_manager.frame_new({title:"Trackster",type:"url",content:i+"/trackster?"+$.param(k)});n.hide_modal()})}})},"View in new visualization":function(){var o=i+"/trackster?"+$.param(k);n.Galaxy.frame_manager.frame_new({title:"Trackster",type:"url",content:o});n.hide_modal()}})}});return false}}});var a=function(l,j,m,i){var k=new j({model:new l(m)});k.render();if(i){i.append(k.$el)}return k};var h=function(k,i){var j=$("<div/>").appendTo(i);return new f({el:j,model:new c(k)}).render()};return{Dataset:e,TabularDataset:c,DatasetCollection:g,TabularDatasetChunkedView:f,createTabularDatasetChunkedView:h}});
\ No newline at end of file
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/packed/mvc/dataset/hda-base.js
--- a/static/scripts/packed/mvc/dataset/hda-base.js
+++ b/static/scripts/packed/mvc/dataset/hda-base.js
@@ -1,1 +1,1 @@
-var HDABaseView=Backbone.View.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(a){if(a.logger){this.logger=this.model.logger=a.logger}this.log(this+".initialize:",a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];if(!a.urlTemplates){throw ("HDAView needs urlTemplates on initialize")}this.urlTemplates=a.urlTemplates;this.expanded=a.expanded||false;this.model.bind("change",function(d,c){var b=_.omit(this.model.changedAttributes(),"display_apps","display_types");if(_.keys(b).length){this.render()}else{if(this.expanded){this._render_displayApps()}}},this)},render:function(){var b=this,e=this.model.get("id"),c=this.model.get("state"),a=$("<div/>").attr("id","historyItem-"+e),d=(this.$el.children().size()===0);this.$el.attr("id","historyItemContainer-"+e);this.urls=this._renderUrls(this.urlTemplates,this.model.toJSON());a.addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+c);a.append(this._render_warnings());a.append(this._render_titleBar());this._setUpBehaviors(a);this.body=$(this._render_body());a.append(this.body);this.$el.fadeOut("fast",function(){b.$el.children().remove();b.$el.append(a).fadeIn("fast",function(){b.log(b+" rendered:",b.$el);var f="rendered";if(d){f+=":initial"}else{if(b.model.inReadyState()){f+=":ready"}}b.trigger(f)})});return this},_renderUrls:function(d,a){var b=this,c={};_.each(d,function(e,f){if(_.isObject(e)){c[f]=b._renderUrls(e,a)}else{if(f==="meta_download"){c[f]=b._renderMetaDownloadUrls(e,a)}else{try{c[f]=_.template(e,a)}catch(g){throw (b+"._renderUrls error: "+g+"\n rendering:"+e+"\n with "+JSON.stringify(a))}}}});return c},_renderMetaDownloadUrls:function(b,a){return _.map(a.meta_files,function(c){return{url:_.template(b,{id:a.id,file_type:c.file_type}),file_type:c.file_type}})},_setUpBehaviors:function(a){a=a||this.$el;make_popup_menus(a);a.find(".tooltip").tooltip({placement:"bottom"})},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());return a},_render_displayButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){this.displayButton=null;return null}var b={icon_class:"display",target:"galaxy_main"};if(this.model.get("purged")){b.enabled=false;b.title=_l("Cannot display datasets removed from disk")}else{if(this.model.get("state")===HistoryDatasetAssociation.STATES.UPLOAD){b.enabled=false;b.title=_l("This dataset must finish uploading before it can be viewed")}else{b.title=_l("View data");b.href=this.urls.display;var a=this;b.on_click=function(){parent.frame_manager.frame_new({title:"Data Viewer",type:"url",location:"center",content:a.urls.display})}}}this.displayButton=new IconButtonView({model:new IconButton(b)});return this.displayButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HDABaseView.templates.titleLink(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});return HDABaseView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var a=this,b=$("<div/>").attr("id","primary-actions-"+this.model.get("id"));_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var a=HDABaseView.templates.downloadLinks(_.extend(this.model.toJSON(),{urls:this.urls}));return $(a.trim())},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_displayAppArea:function(){return $("<div/>").addClass("display-apps")},_render_displayApps:function(c){c=c||this.$el;var d=c.find("div.display-apps"),a=this.model.get("display_types"),b=this.model.get("display_apps");if((!this.model.hasData())||(!c||!c.length)||(!d.length)){return}d.html(null);if(!_.isEmpty(a)){d.append(HDABaseView.templates.displayApps({displayApps:a}))}if(!_.isEmpty(b)){d.append(HDABaseView.templates.displayApps({displayApps:b}))}},_render_peek:function(){var a=this.model.get("peek");if(!a){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(a))},_render_body:function(){var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: none");if(this.expanded){this._render_body_html(a);a.css("display","block")}return a},_render_body_html:function(a){a.html("");switch(this.model.get("state")){case HistoryDatasetAssociation.STATES.NEW:this._render_body_new(a);break;case HistoryDatasetAssociation.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryDatasetAssociation.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryDatasetAssociation.STATES.PAUSED:this._render_body_paused(a);break;case HistoryDatasetAssociation.STATES.QUEUED:this._render_body_queued(a);break;case HistoryDatasetAssociation.STATES.RUNNING:this._render_body_running(a);break;case HistoryDatasetAssociation.STATES.ERROR:this._render_body_error(a);break;case HistoryDatasetAssociation.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryDatasetAssociation.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryDatasetAssociation.STATES.EMPTY:this._render_body_empty(a);break;case HistoryDatasetAssociation.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryDatasetAssociation.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'))}a.append('<div style="clear: both"></div>');this._setUpBehaviors(a)},_render_body_new:function(b){var a=_l("This is a new dataset and not all of its data are available yet");b.append($("<div>"+_l(a)+"</div>"))},_render_body_not_viewable:function(a){a.append($("<div>"+_l("You do not have permission to view dataset")+"</div>"))},_render_body_uploading:function(a){a.append($("<div>"+_l("Dataset is uploading")+"</div>"))},_render_body_queued:function(a){a.append($("<div>"+_l("Job is waiting to run")+"</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_paused:function(a){a.append($("<div>"+_l("Job is paused. Use the history menu to resume")+"</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_running:function(a){a.append("<div>"+_l("Job is currently running")+"</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append((_l("An error occurred with this dataset")+": <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton])))},_render_body_discarded:function(a){a.append("<div>"+_l("The job creating this dataset was cancelled before completion")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_setting_metadata:function(a){a.append($("<div>"+_l("Metadata is being auto-detected")+".</div>"))},_render_body_empty:function(a){a.append($("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_failed_metadata:function(a){a.append($(HDABaseView.templates.failedMetadata(_.extend(this.model.toJSON(),{urls:this.urls}))));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));a.append('<div class="clear"/>');a.append(this._render_displayAppArea());this._render_displayApps(a);a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility"},toggleBodyVisibility:function(c,a){var b=this;this.expanded=(a===undefined)?(!this.body.is(":visible")):(a);if(this.expanded){b._render_body_html(b.body);this.body.slideDown("fast",function(){b.trigger("body-expanded",b.model.get("id"))})}else{this.body.slideUp("fast",function(){b.trigger("body-collapsed",b.model.get("id"))})}},remove:function(b){var a=this;this.$el.fadeOut("fast",function(){a.$el.remove();a.off();if(b){b()}})},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+a+")"}});HDABaseView.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-hda-warning-messages"],titleLink:Handlebars.templates["template-hda-titleLink"],hdaSummary:Handlebars.templates["template-hda-hdaSummary"],downloadLinks:Handlebars.templates["template-hda-downloadLinks"],failedMetadata:Handlebars.templates["template-hda-failedMetadata"],displayApps:Handlebars.templates["template-hda-displayApps"]};
\ No newline at end of file
+var HDABaseView=Backbone.View.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(a){if(a.logger){this.logger=this.model.logger=a.logger}this.log(this+".initialize:",a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];if(!a.urlTemplates){throw ("HDAView needs urlTemplates on initialize")}this.urlTemplates=a.urlTemplates;this.expanded=a.expanded||false;this.model.bind("change",function(d,c){var b=_.omit(this.model.changedAttributes(),"display_apps","display_types");if(_.keys(b).length){this.render()}else{if(this.expanded){this._render_displayApps()}}},this)},render:function(){var b=this,e=this.model.get("id"),c=this.model.get("state"),a=$("<div/>").attr("id","historyItem-"+e),d=(this.$el.children().size()===0);this.$el.attr("id","historyItemContainer-"+e);this.urls=this._renderUrls(this.urlTemplates,this.model.toJSON());a.addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+c);a.append(this._render_warnings());a.append(this._render_titleBar());this._setUpBehaviors(a);this.body=$(this._render_body());a.append(this.body);this.$el.fadeOut("fast",function(){b.$el.children().remove();b.$el.append(a).fadeIn("fast",function(){b.log(b+" rendered:",b.$el);var f="rendered";if(d){f+=":initial"}else{if(b.model.inReadyState()){f+=":ready"}}b.trigger(f)})});return this},_renderUrls:function(d,a){var b=this,c={};_.each(d,function(e,f){if(_.isObject(e)){c[f]=b._renderUrls(e,a)}else{if(f==="meta_download"){c[f]=b._renderMetaDownloadUrls(e,a)}else{try{c[f]=_.template(e,a)}catch(g){throw (b+"._renderUrls error: "+g+"\n rendering:"+e+"\n with "+JSON.stringify(a))}}}});return c},_renderMetaDownloadUrls:function(b,a){return _.map(a.meta_files,function(c){return{url:_.template(b,{id:a.id,file_type:c.file_type}),file_type:c.file_type}})},_setUpBehaviors:function(a){a=a||this.$el;make_popup_menus(a);a.find(".tooltip").tooltip({placement:"bottom"})},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());return a},_render_displayButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){this.displayButton=null;return null}var b={icon_class:"display",target:"galaxy_main"};if(this.model.get("purged")){b.enabled=false;b.title=_l("Cannot display datasets removed from disk")}else{if(this.model.get("state")===HistoryDatasetAssociation.STATES.UPLOAD){b.enabled=false;b.title=_l("This dataset must finish uploading before it can be viewed")}else{b.title=_l("View data");b.href=this.urls.display;var a=this;b.on_click=function(){Galaxy.frame_manager.frame_new({title:"Data Viewer",type:"url",location:"center",content:a.urls.display})}}}this.displayButton=new IconButtonView({model:new IconButton(b)});return this.displayButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HDABaseView.templates.titleLink(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});return HDABaseView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var a=this,b=$("<div/>").attr("id","primary-actions-"+this.model.get("id"));_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var a=HDABaseView.templates.downloadLinks(_.extend(this.model.toJSON(),{urls:this.urls}));return $(a.trim())},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_displayAppArea:function(){return $("<div/>").addClass("display-apps")},_render_displayApps:function(c){c=c||this.$el;var d=c.find("div.display-apps"),a=this.model.get("display_types"),b=this.model.get("display_apps");if((!this.model.hasData())||(!c||!c.length)||(!d.length)){return}d.html(null);if(!_.isEmpty(a)){d.append(HDABaseView.templates.displayApps({displayApps:a}))}if(!_.isEmpty(b)){d.append(HDABaseView.templates.displayApps({displayApps:b}))}},_render_peek:function(){var a=this.model.get("peek");if(!a){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(a))},_render_body:function(){var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: none");if(this.expanded){this._render_body_html(a);a.css("display","block")}return a},_render_body_html:function(a){a.html("");switch(this.model.get("state")){case HistoryDatasetAssociation.STATES.NEW:this._render_body_new(a);break;case HistoryDatasetAssociation.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryDatasetAssociation.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryDatasetAssociation.STATES.PAUSED:this._render_body_paused(a);break;case HistoryDatasetAssociation.STATES.QUEUED:this._render_body_queued(a);break;case HistoryDatasetAssociation.STATES.RUNNING:this._render_body_running(a);break;case HistoryDatasetAssociation.STATES.ERROR:this._render_body_error(a);break;case HistoryDatasetAssociation.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryDatasetAssociation.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryDatasetAssociation.STATES.EMPTY:this._render_body_empty(a);break;case HistoryDatasetAssociation.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryDatasetAssociation.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'))}a.append('<div style="clear: both"></div>');this._setUpBehaviors(a)},_render_body_new:function(b){var a=_l("This is a new dataset and not all of its data are available yet");b.append($("<div>"+_l(a)+"</div>"))},_render_body_not_viewable:function(a){a.append($("<div>"+_l("You do not have permission to view dataset")+"</div>"))},_render_body_uploading:function(a){a.append($("<div>"+_l("Dataset is uploading")+"</div>"))},_render_body_queued:function(a){a.append($("<div>"+_l("Job is waiting to run")+"</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_paused:function(a){a.append($("<div>"+_l("Job is paused. Use the history menu to resume")+"</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_running:function(a){a.append("<div>"+_l("Job is currently running")+"</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append((_l("An error occurred with this dataset")+": <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton])))},_render_body_discarded:function(a){a.append("<div>"+_l("The job creating this dataset was cancelled before completion")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_setting_metadata:function(a){a.append($("<div>"+_l("Metadata is being auto-detected")+".</div>"))},_render_body_empty:function(a){a.append($("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_failed_metadata:function(a){a.append($(HDABaseView.templates.failedMetadata(_.extend(this.model.toJSON(),{urls:this.urls}))));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));a.append('<div class="clear"/>');a.append(this._render_displayAppArea());this._render_displayApps(a);a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility"},toggleBodyVisibility:function(c,a){var b=this;this.expanded=(a===undefined)?(!this.body.is(":visible")):(a);if(this.expanded){b._render_body_html(b.body);this.body.slideDown("fast",function(){b.trigger("body-expanded",b.model.get("id"))})}else{this.body.slideUp("fast",function(){b.trigger("body-collapsed",b.model.get("id"))})}},remove:function(b){var a=this;this.$el.fadeOut("fast",function(){a.$el.remove();a.off();if(b){b()}})},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+a+")"}});HDABaseView.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-hda-warning-messages"],titleLink:Handlebars.templates["template-hda-titleLink"],hdaSummary:Handlebars.templates["template-hda-hdaSummary"],downloadLinks:Handlebars.templates["template-hda-downloadLinks"],failedMetadata:Handlebars.templates["template-hda-failedMetadata"],displayApps:Handlebars.templates["template-hda-displayApps"]};
\ No newline at end of file
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/packed/mvc/dataset/hda-edit.js
--- a/static/scripts/packed/mvc/dataset/hda-edit.js
+++ b/static/scripts/packed/mvc/dataset/hda-edit.js
@@ -1,1 +1,1 @@
-var HDAEditView=HDABaseView.extend(LoggableMixin).extend({initialize:function(a){HDABaseView.prototype.initialize.call(this,a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton]},_setUpBehaviors:function(c){HDABaseView.prototype._setUpBehaviors.call(this,c);var a=this,b=this.urls.purge,d=c.find("#historyItemPurger-"+this.model.get("id"));if(d){d.attr("href",["javascript","void(0)"].join(":"));d.click(function(e){var f=jQuery.ajax(b);f.success(function(i,g,h){a.model.set("purged",true);a.trigger("purged",a)});f.error(function(h,g,i){a.trigger("error",_l("Unable to purge this dataset"),h,g,i)})})}},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());a.append(this._render_editButton());a.append(this._render_deleteButton());return a},_render_editButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===HistoryDatasetAssociation.STATES.UPLOAD)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.editButton=null;return null}var c=this.model.get("purged"),a=this.model.get("deleted"),b={title:_l("Edit Attributes"),href:this.urls.edit,target:"galaxy_main",icon_class:"edit"};if(a||c){b.enabled=false;if(c){b.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(a){b.title=_l("Undelete dataset to edit attributes")}}}this.editButton=new IconButtonView({model:new IconButton(b)});return this.editButton.render().$el},_render_deleteButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.deleteButton=null;return null}var a=this,b=a.urls["delete"],c={title:_l("Delete"),href:b,id:"historyItemDeleter-"+this.model.get("id"),icon_class:"delete",on_click:function(){$.ajax({url:b,type:"POST",error:function(){a.$el.show()},success:function(){a.model.set({deleted:true})}})}};if(this.model.get("deleted")||this.model.get("purged")){c={title:_l("Dataset is already deleted"),icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(c)});return this.deleteButton.render().$el},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){_.extend(a,{dbkey_unknown_and_editable:true})}return HDABaseView.templates.hdaSummary(a)},_render_errButton:function(){if(this.model.get("state")!==HistoryDatasetAssociation.STATES.ERROR){this.errButton=null;return null}this.errButton=new IconButtonView({model:new IconButton({title:_l("View or report this error"),href:this.urls.report_error,target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_rerunButton:function(){this.rerunButton=new IconButtonView({model:new IconButton({title:_l("Run this job again"),href:this.urls.rerun,target:"galaxy_main",icon_class:"arrow-circle"})});return this.rerunButton.render().$el},_render_visualizationsButton:function(){var a=this.model.get("visualizations");if((!this.model.hasData())||(_.isEmpty(a))){this.visualizationsButton=null;return null}if(_.isObject(a[0])){return this._render_visualizationsFrameworkButton(a)}if(!this.urls.visualization){this.visualizationsButton=null;return null}var c=this.model.get("dbkey"),f=this.urls.visualization,d={},g={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(c){g.dbkey=c}this.visualizationsButton=new IconButtonView({model:new IconButton({title:_l("Visualize"),href:this.urls.visualization,icon_class:"chart_curve"})});var b=this.visualizationsButton.render().$el;b.addClass("visualize-icon");function e(h){switch(h){case"trackster":return create_trackster_action_fn(f,g,c);case"scatterplot":return create_scatterplot_action_fn(f,g);default:return function(){parent.frame_manager.frame_new({title:"Visualization",type:"url",content:f+"/"+h+"?"+$.param(g)})}}}if(a.length===1){b.attr("title",a[0]);b.click(e(a[0]))}else{_.each(a,function(i){var h=i.charAt(0).toUpperCase()+i.slice(1);d[_l(h)]=e(i)});make_popupmenu(b,d)}return b},_render_visualizationsFrameworkButton:function(a){if(!(this.model.hasData())||!(a&&!_.isEmpty(a))){this.visualizationsButton=null;return null}this.visualizationsButton=new IconButtonView({model:new IconButton({title:_l("Visualize"),icon_class:"chart_curve"})});var c=this.visualizationsButton.render().$el;c.addClass("visualize-icon");if(_.keys(a).length===1){c.attr("title",_.keys(a)[0]);c.attr("href",_.values(a)[0])}else{var d=[];_.each(a,function(e){d.push(e)});var b=new PopupMenu(c,d)}return c},_render_secondaryActionButtons:function(b){var c=$("<div/>"),a=this;c.attr("style","float: right;").attr("id","secondary-actions-"+this.model.get("id"));_.each(b,function(d){c.append(d.call(a))});return c},_render_tagButton:function(){if(!(this.model.hasData())||(!this.urls.tags.get)){this.tagButton=null;return null}this.tagButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset tags"),target:"galaxy_main",href:this.urls.tags.get,icon_class:"tags"})});return this.tagButton.render().$el},_render_annotateButton:function(){if(!(this.model.hasData())||(!this.urls.annotation.get)){this.annotateButton=null;return null}this.annotateButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset annotation"),target:"galaxy_main",icon_class:"annotate"})});return this.annotateButton.render().$el},_render_tagArea:function(){if(!this.urls.tags.set){return null}return $(HDAEditView.templates.tagArea(_.extend(this.model.toJSON(),{urls:this.urls})).trim())},_render_annotationArea:function(){if(!this.urls.annotation.get){return null}return $(HDAEditView.templates.annotationArea(_.extend(this.model.toJSON(),{urls:this.urls})).trim())},_render_body_error:function(a){HDABaseView.prototype._render_body_error.call(this,a);var b=a.find("#primary-actions-"+this.model.get("id"));b.prepend(this._render_errButton())},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton,this._render_visualizationsButton]));a.append(this._render_secondaryActionButtons([this._render_tagButton,this._render_annotateButton]));a.append('<div class="clear"/>');a.append(this._render_tagArea());a.append(this._render_annotationArea());a.append(this._render_displayAppArea());this._render_displayApps(a);a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility","click a.icon-button.tags":"loadAndDisplayTags","click a.icon-button.annotate":"loadAndDisplayAnnotation"},loadAndDisplayTags:function(c){this.log(this+".loadAndDisplayTags",c);var a=this,d=this.$el.find(".tag-area"),b=d.find(".tag-elt");if(d.is(":hidden")){if(!jQuery.trim(b.html())){$.ajax({url:this.urls.tags.get,error:function(g,e,f){a.log("Tagging failed",g,e,f);a.trigger("error",_l("Tagging failed"),g,e,f)},success:function(e){b.html(e);b.find(".tooltip").tooltip();d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},loadAndDisplayAnnotation:function(b){this.log(this+".loadAndDisplayAnnotation",b);var d=this.$el.find(".annotation-area"),c=d.find(".annotation-elt"),a=this.urls.annotation.set;if(d.is(":hidden")){if(!jQuery.trim(c.html())){$.ajax({url:this.urls.annotation.get,error:function(){view.log("Annotation failed",xhr,status,error);view.trigger("error",_l("Annotation failed"),xhr,status,error)},success:function(e){if(e===""){e="<em>"+_l("Describe or add notes to dataset")+"</em>"}c.html(e);d.find(".tooltip").tooltip();async_save_text(c.attr("id"),c.attr("id"),a,"new_annotation",18,true,4);d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDAView("+a+")"}});HDAEditView.templates={tagArea:Handlebars.templates["template-hda-tagArea"],annotationArea:Handlebars.templates["template-hda-annotationArea"]};function create_scatterplot_action_fn(a,b){action=function(){parent.frame_manager.frame_new({title:"Scatterplot",type:"url",content:a+"/scatterplot?"+$.param(b),location:"center"});$("div.popmenu-wrapper").remove();return false};return action}function create_trackster_action_fn(a,c,b){return function(){var d={};if(b){d["f-dbkey"]=b}$.ajax({url:a+"/list_tracks?"+$.param(d),dataType:"html",error:function(){alert(_l("Could not add this dataset to browser")+".")},success:function(e){var f=window.parent;f.show_modal(_l("View Data in a New or Saved Visualization"),"",{Cancel:function(){f.hide_modal()},"View in saved visualization":function(){f.show_modal(_l("Add Data to Saved Visualization"),e,{Cancel:function(){f.hide_modal()},"Add to visualization":function(){$(f.document).find("input[name=id]:checked").each(function(){var g=$(this).val();c.id=g;f.hide_modal();f.frame_manager.frame_new({title:"Trackster",type:"url",content:a+"/trackster?"+$.param(c)})})}})},"View in new visualization":function(){f.hide_modal();f.frame_manager.frame_new({title:"Trackster",type:"url",content:a+"/trackster?"+$.param(c)})}})}});return false}};
\ No newline at end of file
+var HDAEditView=HDABaseView.extend(LoggableMixin).extend({initialize:function(a){HDABaseView.prototype.initialize.call(this,a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton]},_setUpBehaviors:function(c){HDABaseView.prototype._setUpBehaviors.call(this,c);var a=this,b=this.urls.purge,d=c.find("#historyItemPurger-"+this.model.get("id"));if(d){d.attr("href",["javascript","void(0)"].join(":"));d.click(function(e){var f=jQuery.ajax(b);f.success(function(i,g,h){a.model.set("purged",true);a.trigger("purged",a)});f.error(function(h,g,i){a.trigger("error",_l("Unable to purge this dataset"),h,g,i)})})}},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());a.append(this._render_editButton());a.append(this._render_deleteButton());return a},_render_editButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===HistoryDatasetAssociation.STATES.UPLOAD)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.editButton=null;return null}var c=this.model.get("purged"),a=this.model.get("deleted"),b={title:_l("Edit Attributes"),href:this.urls.edit,target:"galaxy_main",icon_class:"edit"};if(a||c){b.enabled=false;if(c){b.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(a){b.title=_l("Undelete dataset to edit attributes")}}}this.editButton=new IconButtonView({model:new IconButton(b)});return this.editButton.render().$el},_render_deleteButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.deleteButton=null;return null}var a=this,b=a.urls["delete"],c={title:_l("Delete"),href:b,id:"historyItemDeleter-"+this.model.get("id"),icon_class:"delete",on_click:function(){$.ajax({url:b,type:"POST",error:function(){a.$el.show()},success:function(){a.model.set({deleted:true})}})}};if(this.model.get("deleted")||this.model.get("purged")){c={title:_l("Dataset is already deleted"),icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(c)});return this.deleteButton.render().$el},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){_.extend(a,{dbkey_unknown_and_editable:true})}return HDABaseView.templates.hdaSummary(a)},_render_errButton:function(){if(this.model.get("state")!==HistoryDatasetAssociation.STATES.ERROR){this.errButton=null;return null}this.errButton=new IconButtonView({model:new IconButton({title:_l("View or report this error"),href:this.urls.report_error,target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_rerunButton:function(){this.rerunButton=new IconButtonView({model:new IconButton({title:_l("Run this job again"),href:this.urls.rerun,target:"galaxy_main",icon_class:"arrow-circle"})});return this.rerunButton.render().$el},_render_visualizationsButton:function(){var a=this.model.get("visualizations");if((!this.model.hasData())||(_.isEmpty(a))){this.visualizationsButton=null;return null}if(_.isObject(a[0])){return this._render_visualizationsFrameworkButton(a)}if(!this.urls.visualization){this.visualizationsButton=null;return null}var c=this.model.get("dbkey"),f=this.urls.visualization,d={},g={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(c){g.dbkey=c}this.visualizationsButton=new IconButtonView({model:new IconButton({title:_l("Visualize"),href:this.urls.visualization,icon_class:"chart_curve"})});var b=this.visualizationsButton.render().$el;b.addClass("visualize-icon");function e(h){switch(h){case"trackster":return create_trackster_action_fn(f,g,c);case"scatterplot":return create_scatterplot_action_fn(f,g);default:return function(){Galaxy.frame_manager.frame_new({title:"Visualization",type:"url",content:f+"/"+h+"?"+$.param(g)})}}}if(a.length===1){b.attr("title",a[0]);b.click(e(a[0]))}else{_.each(a,function(i){var h=i.charAt(0).toUpperCase()+i.slice(1);d[_l(h)]=e(i)});make_popupmenu(b,d)}return b},_render_visualizationsFrameworkButton:function(a){if(!(this.model.hasData())||!(a&&!_.isEmpty(a))){this.visualizationsButton=null;return null}this.visualizationsButton=new IconButtonView({model:new IconButton({title:_l("Visualize"),icon_class:"chart_curve"})});var c=this.visualizationsButton.render().$el;c.addClass("visualize-icon");if(_.keys(a).length===1){c.attr("title",_.keys(a)[0]);c.attr("href",_.values(a)[0])}else{var d=[];_.each(a,function(e){d.push(e)});var b=new PopupMenu(c,d)}return c},_render_secondaryActionButtons:function(b){var c=$("<div/>"),a=this;c.attr("style","float: right;").attr("id","secondary-actions-"+this.model.get("id"));_.each(b,function(d){c.append(d.call(a))});return c},_render_tagButton:function(){if(!(this.model.hasData())||(!this.urls.tags.get)){this.tagButton=null;return null}this.tagButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset tags"),target:"galaxy_main",href:this.urls.tags.get,icon_class:"tags"})});return this.tagButton.render().$el},_render_annotateButton:function(){if(!(this.model.hasData())||(!this.urls.annotation.get)){this.annotateButton=null;return null}this.annotateButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset annotation"),target:"galaxy_main",icon_class:"annotate"})});return this.annotateButton.render().$el},_render_tagArea:function(){if(!this.urls.tags.set){return null}return $(HDAEditView.templates.tagArea(_.extend(this.model.toJSON(),{urls:this.urls})).trim())},_render_annotationArea:function(){if(!this.urls.annotation.get){return null}return $(HDAEditView.templates.annotationArea(_.extend(this.model.toJSON(),{urls:this.urls})).trim())},_render_body_error:function(a){HDABaseView.prototype._render_body_error.call(this,a);var b=a.find("#primary-actions-"+this.model.get("id"));b.prepend(this._render_errButton())},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton,this._render_visualizationsButton]));a.append(this._render_secondaryActionButtons([this._render_tagButton,this._render_annotateButton]));a.append('<div class="clear"/>');a.append(this._render_tagArea());a.append(this._render_annotationArea());a.append(this._render_displayAppArea());this._render_displayApps(a);a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility","click a.icon-button.tags":"loadAndDisplayTags","click a.icon-button.annotate":"loadAndDisplayAnnotation"},loadAndDisplayTags:function(c){this.log(this+".loadAndDisplayTags",c);var a=this,d=this.$el.find(".tag-area"),b=d.find(".tag-elt");if(d.is(":hidden")){if(!jQuery.trim(b.html())){$.ajax({url:this.urls.tags.get,error:function(g,e,f){a.log("Tagging failed",g,e,f);a.trigger("error",_l("Tagging failed"),g,e,f)},success:function(e){b.html(e);b.find(".tooltip").tooltip();d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},loadAndDisplayAnnotation:function(b){this.log(this+".loadAndDisplayAnnotation",b);var d=this.$el.find(".annotation-area"),c=d.find(".annotation-elt"),a=this.urls.annotation.set;if(d.is(":hidden")){if(!jQuery.trim(c.html())){$.ajax({url:this.urls.annotation.get,error:function(){view.log("Annotation failed",xhr,status,error);view.trigger("error",_l("Annotation failed"),xhr,status,error)},success:function(e){if(e===""){e="<em>"+_l("Describe or add notes to dataset")+"</em>"}c.html(e);d.find(".tooltip").tooltip();async_save_text(c.attr("id"),c.attr("id"),a,"new_annotation",18,true,4);d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDAView("+a+")"}});HDAEditView.templates={tagArea:Handlebars.templates["template-hda-tagArea"],annotationArea:Handlebars.templates["template-hda-annotationArea"]};function create_scatterplot_action_fn(a,b){action=function(){Galaxy.frame_manager.frame_new({title:"Scatterplot",type:"url",content:a+"/scatterplot?"+$.param(b),location:"center"});$("div.popmenu-wrapper").remove();return false};return action}function create_trackster_action_fn(a,c,b){return function(){var d={};if(b){d["f-dbkey"]=b}$.ajax({url:a+"/list_tracks?"+$.param(d),dataType:"html",error:function(){alert(_l("Could not add this dataset to browser")+".")},success:function(e){var f=window.parent;f.show_modal(_l("View Data in a New or Saved Visualization"),"",{Cancel:function(){f.hide_modal()},"View in saved visualization":function(){f.show_modal(_l("Add Data to Saved Visualization"),e,{Cancel:function(){f.hide_modal()},"Add to visualization":function(){$(f.document).find("input[name=id]:checked").each(function(){var g=$(this).val();c.id=g;f.hide_modal();Galaxy.frame_manager.frame_new({title:"Trackster",type:"url",content:a+"/trackster?"+$.param(c)})})}})},"View in new visualization":function(){f.hide_modal();Galaxy.frame_manager.frame_new({title:"Trackster",type:"url",content:a+"/trackster?"+$.param(c)})}})}});return false}};
\ No newline at end of file
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/packed/mvc/history/history-panel.js
--- a/static/scripts/packed/mvc/history/history-panel.js
+++ b/static/scripts/packed/mvc/history/history-panel.js
@@ -1,1 +1,1 @@
-var HistoryPanel=Backbone.View.extend(LoggableMixin).extend({el:"body.historyPage",HDAView:HDAEditView,events:{"click #history-tag":"loadAndDisplayTags","click #message-container":"removeMessage"},initialize:function(a){if(a.logger){this.logger=this.model.logger=a.logger}this.log(this+".initialize:",a);if(!a.urlTemplates){throw (this+" needs urlTemplates on initialize")}if(!a.urlTemplates.history){throw (this+" needs urlTemplates.history on initialize")}if(!a.urlTemplates.hda){throw (this+" needs urlTemplates.hda on initialize")}this.urlTemplates=a.urlTemplates.history;this.hdaUrlTemplates=a.urlTemplates.hda;this._setUpWebStorage(a.initiallyExpanded,a.show_deleted,a.show_hidden);this._setUpEventHandlers();this.hdaViews={};this.urls={}},_setUpEventHandlers:function(){this.model.bind("change:nice_size",this.updateHistoryDiskSize,this);this.model.bind("error",function(d,c,b,a){this.displayMessage("error",d);this.model.attributes.error=undefined},this);this.model.hdas.bind("add",this.add,this);this.model.hdas.bind("reset",this.addAll,this);this.model.hdas.bind("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.bind("change:purged",function(a){this.model.fetch()},this);this.model.hdas.bind("state:ready",function(b,c,a){if((!b.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(b.get("id"))}},this);this.bind("error",function(d,c,b,a){this.displayMessage("error",d)});if(this.logger){this.bind("all",function(a){this.log(this+"",arguments)},this)}},_setUpWebStorage:function(b,a,c){this.storage=new PersistantStorage("HistoryView."+this.model.get("id"),{expandedHdas:{},show_deleted:false,show_hidden:false});this.log(this+" (prev) storage:",JSON.stringify(this.storage.get(),null,2));if(b){this.storage.set("exandedHdas",b)}if((a===true)||(a===false)){this.storage.set("show_deleted",a)}if((c===true)||(c===false)){this.storage.set("show_hidden",c)}this.show_deleted=this.storage.get("show_deleted");this.show_hidden=this.storage.get("show_hidden");this.log(this+" (init'd) storage:",this.storage.get())},add:function(a){this.render()},addAll:function(){this.render()},handleHdaDeletionChange:function(a){if(a.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(a.get("id"))}},removeHdaView:function(c,b){var a=this.hdaViews[c];if(!a){return}a.remove(b);delete this.hdaViews[c];if(_.isEmpty(this.hdaViews)){this.render()}},render:function(){var b=this,d=b.toString()+".set-up",c=$("<div/>"),a=this.model.toJSON(),e=(this.$el.children().size()===0);a.urls=this._renderUrls(a);c.append(HistoryPanel.templates.historyPanel(a));c.find(".tooltip").tooltip({placement:"bottom"});if(!this.model.hdas.length||!this.renderItems(c.find("#"+this.model.get("id")+"-datasets"))){c.find("#emptyHistoryMessage").show()}$(b).queue(d,function(f){b.$el.fadeOut("fast",function(){f()})});$(b).queue(d,function(f){b.$el.html("");b.$el.append(c.children());b.$el.fadeIn("fast",function(){f()})});$(b).queue(d,function(f){this.log(b+" rendered:",b.$el);b._setUpBehaviours();if(e){b.trigger("rendered:initial")}else{b.trigger("rendered")}f()});$(b).dequeue(d);return this},_renderUrls:function(a){var b=this;b.urls={};_.each(this.urlTemplates,function(d,c){b.urls[c]=_.template(d,a)});return b.urls},renderItems:function(b){this.hdaViews={};var a=this,c=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"));_.each(c,function(f){var e=f.get("id"),d=a.storage.get("expandedHdas").get(e);a.hdaViews[e]=new a.HDAView({model:f,expanded:d,urlTemplates:a.hdaUrlTemplates,logger:a.logger});a._setUpHdaListeners(a.hdaViews[e]);b.prepend(a.hdaViews[e].render().$el)});return c.length},_setUpHdaListeners:function(b){var a=this;b.bind("body-expanded",function(c){a.storage.get("expandedHdas").set(c,true)});b.bind("body-collapsed",function(c){a.storage.get("expandedHdas").deleteKey(c)});b.bind("error",function(f,e,c,d){a.displayMessage("error",f)})},_setUpBehaviours:function(){if(!(this.model.get("user")&&this.model.get("user").email)){return}var a=this.$("#history-annotation-area");this.$("#history-annotate").click(function(){if(a.is(":hidden")){a.slideDown("fast")}else{a.slideUp("fast")}return false});async_save_text("history-name-container","history-name",this.urls.rename,"new_name",18);async_save_text("history-annotation-container","history-annotation",this.urls.annotate,"new_annotation",18,true,4)},updateHistoryDiskSize:function(){this.$el.find("#history-size").text(this.model.get("nice_size"))},showQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(a.is(":hidden")){a.slideDown("fast")}},hideQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(!a.is(":hidden")){a.slideUp("fast")}},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.render();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.render();return this.storage.get("show_hidden")},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(a){a.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},loadAndDisplayTags:function(d){this.log(this+".loadAndDisplayTags",d);var b=this,e=this.$el.find("#history-tag-area"),c=e.find(".tag-elt");this.log("\t tagArea",e," tagElt",c);if(e.is(":hidden")){if(!jQuery.trim(c.html())){var a=this;$.ajax({url:a.urls.tag,error:function(h,g,f){b.log("Error loading tag area html",h,g,f);b.trigger("error",_l("Tagging failed"),h,g,f)},success:function(f){c.html(f);c.find(".tooltip").tooltip();e.slideDown("fast")}})}else{e.slideDown("fast")}}else{e.slideUp("fast")}return false},displayMessage:function(c,d){var b=this.$el.find("#message-container"),a=$("<div/>").addClass(c+"message").text(d);b.html(a)},removeMessage:function(){var a=this.$el.find("#message-container");a.html(null)},scrollToTop:function(){$(document).scrollTop(0);return this},scrollIntoView:function(b,c){if(!c){$(document).scrollTop(b);return this}var a=window,d=this.$el.parent(),f=$(a).innerHeight(),e=(f/2)-(c/2);$(d).scrollTop(b-e);return this},scrollToId:function(b){if((!b)||(!this.hdaViews[b])){return this}var a=this.hdaViews[b].$el;this.scrollIntoView(a.offset().top,a.outerHeight());return this},scrollToHid:function(a){var b=this.model.hdas.getByHid(a);if(!b){return this}return this.scrollToId(b.id)},toString:function(){var a=this.model.get("name")||"";return"HistoryPanel("+a+")"}});HistoryPanel.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};
\ No newline at end of file
+var HistoryPanel=Backbone.View.extend(LoggableMixin).extend({el:"body.historyPage",HDAView:HDAEditView,events:{"click #history-tag":"loadAndDisplayTags","click #message-container":"removeMessage"},initialize:function(a){if(a.logger){this.logger=this.model.logger=a.logger}this.log(this+".initialize:",a);if(!a.urlTemplates){throw (this+" needs urlTemplates on initialize")}if(!a.urlTemplates.history){throw (this+" needs urlTemplates.history on initialize")}if(!a.urlTemplates.hda){throw (this+" needs urlTemplates.hda on initialize")}this.urlTemplates=a.urlTemplates.history;this.hdaUrlTemplates=a.urlTemplates.hda;this._setUpWebStorage(a.initiallyExpanded,a.show_deleted,a.show_hidden);this._setUpEventHandlers();this.hdaViews={};this.urls={}},refresh:function(){window.location=window.location},_setUpEventHandlers:function(){this.model.bind("change:nice_size",this.updateHistoryDiskSize,this);this.model.bind("error",function(d,c,b,a){this.displayMessage("error",d);this.model.attributes.error=undefined},this);this.model.hdas.bind("add",this.add,this);this.model.hdas.bind("reset",this.addAll,this);this.model.hdas.bind("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.bind("change:purged",function(a){this.model.fetch()},this);this.model.hdas.bind("state:ready",function(b,c,a){if((!b.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(b.get("id"))}},this);this.bind("error",function(d,c,b,a){this.displayMessage("error",d)});if(this.logger){this.bind("all",function(a){this.log(this+"",arguments)},this)}},_setUpWebStorage:function(b,a,c){this.storage=new PersistantStorage("HistoryView."+this.model.get("id"),{expandedHdas:{},show_deleted:false,show_hidden:false});this.log(this+" (prev) storage:",JSON.stringify(this.storage.get(),null,2));if(b){this.storage.set("exandedHdas",b)}if((a===true)||(a===false)){this.storage.set("show_deleted",a)}if((c===true)||(c===false)){this.storage.set("show_hidden",c)}this.show_deleted=this.storage.get("show_deleted");this.show_hidden=this.storage.get("show_hidden");this.log(this+" (init'd) storage:",this.storage.get())},add:function(a){this.render()},addAll:function(){this.render()},handleHdaDeletionChange:function(a){if(a.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(a.get("id"))}},removeHdaView:function(c,b){var a=this.hdaViews[c];if(!a){return}a.remove(b);delete this.hdaViews[c];if(_.isEmpty(this.hdaViews)){this.render()}},render:function(){var b=this,d=b.toString()+".set-up",c=$("<div/>"),a=this.model.toJSON(),e=(this.$el.children().size()===0);a.urls=this._renderUrls(a);c.append(HistoryPanel.templates.historyPanel(a));c.find(".tooltip").tooltip({placement:"bottom"});if(!this.model.hdas.length||!this.renderItems(c.find("#"+this.model.get("id")+"-datasets"))){c.find("#emptyHistoryMessage").show()}$(b).queue(d,function(f){b.$el.fadeOut("fast",function(){f()})});$(b).queue(d,function(f){b.$el.html("");b.$el.append(c.children());b.$el.fadeIn("fast",function(){f()})});$(b).queue(d,function(f){this.log(b+" rendered:",b.$el);b._setUpBehaviours();if(e){b.trigger("rendered:initial")}else{b.trigger("rendered")}f()});$(b).dequeue(d);return this},_renderUrls:function(a){var b=this;b.urls={};_.each(this.urlTemplates,function(d,c){b.urls[c]=_.template(d,a)});return b.urls},renderItems:function(b){this.hdaViews={};var a=this,c=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"));_.each(c,function(f){var e=f.get("id"),d=a.storage.get("expandedHdas").get(e);a.hdaViews[e]=new a.HDAView({model:f,expanded:d,urlTemplates:a.hdaUrlTemplates,logger:a.logger});a._setUpHdaListeners(a.hdaViews[e]);b.prepend(a.hdaViews[e].render().$el)});return c.length},_setUpHdaListeners:function(b){var a=this;b.bind("body-expanded",function(c){a.storage.get("expandedHdas").set(c,true)});b.bind("body-collapsed",function(c){a.storage.get("expandedHdas").deleteKey(c)});b.bind("error",function(f,e,c,d){a.displayMessage("error",f)})},_setUpBehaviours:function(){if(!(this.model.get("user")&&this.model.get("user").email)){return}var a=this.$("#history-annotation-area");this.$("#history-annotate").click(function(){if(a.is(":hidden")){a.slideDown("fast")}else{a.slideUp("fast")}return false});async_save_text("history-name-container","history-name",this.urls.rename,"new_name",18);async_save_text("history-annotation-container","history-annotation",this.urls.annotate,"new_annotation",18,true,4)},updateHistoryDiskSize:function(){this.$el.find("#history-size").text(this.model.get("nice_size"))},showQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(a.is(":hidden")){a.slideDown("fast")}},hideQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(!a.is(":hidden")){a.slideUp("fast")}},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.render();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.render();return this.storage.get("show_hidden")},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(a){a.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},loadAndDisplayTags:function(d){this.log(this+".loadAndDisplayTags",d);var b=this,e=this.$el.find("#history-tag-area"),c=e.find(".tag-elt");this.log("\t tagArea",e," tagElt",c);if(e.is(":hidden")){if(!jQuery.trim(c.html())){var a=this;$.ajax({url:a.urls.tag,error:function(h,g,f){b.log("Error loading tag area html",h,g,f);b.trigger("error",_l("Tagging failed"),h,g,f)},success:function(f){c.html(f);c.find(".tooltip").tooltip();e.slideDown("fast")}})}else{e.slideDown("fast")}}else{e.slideUp("fast")}return false},displayMessage:function(c,d){var b=this.$el.find("#message-container"),a=$("<div/>").addClass(c+"message").text(d);b.html(a)},removeMessage:function(){var a=this.$el.find("#message-container");a.html(null)},scrollToTop:function(){$(document).scrollTop(0);return this},scrollIntoView:function(b,c){if(!c){$(document).scrollTop(b);return this}var a=window,d=this.$el.parent(),f=$(a).innerHeight(),e=(f/2)-(c/2);$(d).scrollTop(b-e);return this},scrollToId:function(b){if((!b)||(!this.hdaViews[b])){return this}var a=this.hdaViews[b].$el;this.scrollIntoView(a.offset().top,a.outerHeight());return this},scrollToHid:function(a){var b=this.model.hdas.getByHid(a);if(!b){return this}return this.scrollToId(b.id)},toString:function(){var a=this.model.get("name")||"";return"HistoryPanel("+a+")"}});HistoryPanel.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};
\ No newline at end of file
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/packed/utils/galaxy.uploadbox.js
--- /dev/null
+++ b/static/scripts/packed/utils/galaxy.uploadbox.js
@@ -0,0 +1,1 @@
+(function(d){jQuery.event.props.push("dataTransfer");var c={url:"",paramname:"content",maxfilesize:2048,data:{},dragover:function(){},dragleave:function(){},initialize:function(){},start:function(){},progress:function(){},success:function(){},error:function(f,g,h){alert(h)},error_browser:"Your browser does not support drag-and-drop file uploads.",error_filesize:"This file is too large. Please use an FTP client to upload it.",error_default:"The upload failed. Please make sure the file is available and accessible.",text_default:"Drag&drop files here or click to browse your local drive.",text_degrade:"Click here to browse your local drive. <br><br>Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Please upgrade to i.e. Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."};var a=[];var b=-1;var e=false;d.fn.uploadbox=function(n){var f=d.extend({},c,n);var l=window.File&&window.FileReader&&window.FormData&&window.XMLHttpRequest;this.append('<input id="uploadbox_input" type="file" style="display: none" multiple>');this.append('<div id="uploadbox_info"></div>');if(l){this.find("#uploadbox_info").html(f.text_default)}else{this.find("#uploadbox_info").html(f.text_degrade)}this.on("drop",i);this.on("dragover",j);this.on("dragleave",m);this.on("click",function(p){p.stopPropagation();d("#uploadbox_input").trigger(p)});d("#uploadbox_input").change(function(q){var p=q.target.files;o(p)});function i(q){if(!q.dataTransfer){return}var p=q.dataTransfer.files;o(p);q.preventDefault();return false}function j(p){p.preventDefault();f.dragover.call(this,p)}function m(p){p.stopPropagation();f.dragleave.call(this,p)}function g(p){if(p.lengthComputable){f.progress(this.index,this.file,Math.round((p.loaded*100)/p.total))}}function o(r){var q=a.length;for(var p=0;p<r.length;p++){a.push(r[p])}for(var p=q;p<a.length;p++){f.start(p,a[p],"")}if(!e){h()}}function h(){if(b+1==a.length){e=false;return}e=true;var s=++b;try{var q=new FileReader();var t=a[s];var r=t.size;var p=1048576*f.maxfilesize;q.index=s;if(r<p){q.onloadend=function(v){k(s,t)};q.onerror=function(v){f.error(s,t,f.error_default);e=false};q.readAsDataURL(t)}else{f.error(s,t,f.error_filesize);h()}}catch(u){f.error(s,t,u)}}function k(p,r){var s=new FormData();for(var q in f.data){s.append(q,f.data[q])}s.append(f.paramname,r,r.name);var t=new XMLHttpRequest();t.upload.index=p;t.upload.file=r;t.upload.addEventListener("progress",g,false);t.open("POST",f.url,true);t.setRequestHeader("Accept","application/json");t.setRequestHeader("Cache-Control","no-cache");t.setRequestHeader("X-Requested-With","XMLHttpRequest");t.send(s);t.onloadend=function(){var u=null;if(t.responseText){try{u=jQuery.parseJSON(t.responseText)}catch(v){u=t.responseText}}if(t.status<200||t.status>299){f.error(p,r,t.statusText+" (Server Code "+t.status+")");e=false}else{f.success(p,r,u);h()}}}return this}})(jQuery);
\ No newline at end of file
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/scripts/utils/galaxy.uploadbox.js
--- /dev/null
+++ b/static/scripts/utils/galaxy.uploadbox.js
@@ -0,0 +1,258 @@
+/*
+ galaxy upload lib v1.0 - uses FileReader, FormData and XMLHttpRequest
+*/
+;(function($)
+{
+ // add event properties
+ jQuery.event.props.push("dataTransfer");
+
+ // default options
+ var default_opts =
+ {
+ url : '',
+ paramname : 'content',
+ maxfilesize : 2048,
+ data : {},
+ dragover : function() {},
+ dragleave : function() {},
+ initialize : function() {},
+ start : function() {},
+ progress : function() {},
+ success : function() {},
+ error : function(index, file, message) { alert(message); },
+ error_browser : "Your browser does not support drag-and-drop file uploads.",
+ error_filesize : "This file is too large. Please use an FTP client to upload it.",
+ error_default : "The upload failed. Please make sure the file is available and accessible.",
+ text_default : "Drag&drop files here or click to browse your local drive.",
+ text_degrade : "Click here to browse your local drive. <br><br>Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Please upgrade to i.e. Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."
+ }
+
+ // global file queue
+ var queue = [];
+
+ // global counter for file being currently processed
+ var queue_index = -1;
+
+ // global queue status
+ var queue_status = false;
+
+ // attach to element
+ $.fn.uploadbox = function(options)
+ {
+ // parse options
+ var opts = $.extend({}, default_opts, options);
+
+ // compatibility
+ var mode = window.File && window.FileReader && window.FormData && window.XMLHttpRequest;
+
+ // append upload button
+ this.append('<input id="uploadbox_input" type="file" style="display: none" multiple>');
+ this.append('<div id="uploadbox_info"></div>');
+
+ // set info text
+ if (mode)
+ this.find('#uploadbox_info').html(opts.text_default);
+ else
+ this.find('#uploadbox_info').html(opts.text_degrade);
+
+ // attach events
+ this.on('drop', drop);
+ this.on('dragover', dragover);
+ this.on('dragleave', dragleave);
+
+ // attach click event
+ this.on('click', function(e)
+ {
+ e.stopPropagation();
+ $('#uploadbox_input').trigger(e);
+ });
+
+ // attach change event
+ $('#uploadbox_input').change(function(e)
+ {
+ var files = e.target.files;
+ upload(files);
+ });
+
+ // drop event
+ function drop(e)
+ {
+ // check if its a file transfer
+ if(!e.dataTransfer)
+ return;
+
+ // get files from event
+ var files = e.dataTransfer.files;
+
+ // start upload
+ upload(files);
+
+ // prevent default
+ e.preventDefault();
+
+ // return
+ return false;
+ }
+
+ // drag over
+ function dragover(e)
+ {
+ e.preventDefault();
+ opts.dragover.call(this, e);
+ }
+
+ // drag leave
+ function dragleave(e)
+ {
+ e.stopPropagation();
+ opts.dragleave.call(this, e);
+ }
+
+ // progress
+ function progress(e)
+ {
+ // get percentage
+ if (e.lengthComputable)
+ opts.progress(this.index, this.file, Math.round((e.loaded * 100) / e.total));
+ }
+
+ // respond to an upload request
+ function upload(files)
+ {
+ // get current queue size
+ var queue_sofar = queue.length;
+
+ // add new files to queue
+ for (var index = 0; index < files.length; index++)
+ queue.push(files[index]);
+
+ // tell client about new uploads
+ for (var index = queue_sofar; index < queue.length; index++)
+ opts.start(index, queue[index], "");
+
+ // initiate processing loop if process loop is not running already
+ if (!queue_status)
+ process();
+ }
+
+ // process an upload, recursive
+ function process()
+ {
+ // check if for files
+ if (queue_index + 1 == queue.length)
+ {
+ queue_status = false;
+ return;
+ }
+
+ // set status
+ queue_status = true;
+
+ // identify current index
+ var index = ++queue_index;
+
+ // add file to queue
+ try
+ {
+ // load file read
+ var reader = new FileReader();
+
+ // identify maximum file size
+ var file = queue[index];
+ var filesize = file.size;
+ var maxfilesize = 1048576 * opts.maxfilesize;
+
+ // set index
+ reader.index = index;
+ if (filesize < maxfilesize)
+ {
+ // link loadend is always called at the end
+ reader.onloadend = function(e)
+ {
+ send(index, file)
+ };
+
+ // link error
+ reader.onerror = function(e)
+ {
+ opts.error(index, file, opts.error_default);
+ queue_status = false;
+ };
+
+ // read data
+ reader.readAsDataURL(file);
+ } else {
+ // skip file
+ opts.error(index, file, opts.error_filesize);
+
+ // restart process
+ process();
+ }
+ } catch (err)
+ {
+ // parse error
+ opts.error(index, file, err);
+ }
+ }
+
+ // send file
+ function send (index, file)
+ {
+ // construct form data
+ var formData = new FormData();
+ for (var key in opts.data)
+ formData.append(key, opts.data[key]);
+ formData.append(opts.paramname, file, file.name);
+
+ // prepare request
+ var xhr = new XMLHttpRequest();
+
+ // prepare upload progress
+ xhr.upload.index = index;
+ xhr.upload.file = file;
+ xhr.upload.addEventListener('progress', progress, false);
+
+ // open request
+ xhr.open('POST', opts.url, true);
+ xhr.setRequestHeader('Accept', 'application/json');
+ xhr.setRequestHeader('Cache-Control', 'no-cache');
+ xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+ xhr.send(formData);
+
+ // onloadend
+ xhr.onloadend = function()
+ {
+ // retrieve response
+ var response = null;
+ if (xhr.responseText)
+ {
+ try
+ {
+ response = jQuery.parseJSON(xhr.responseText);
+ } catch (e) {
+ response = xhr.responseText;
+ }
+ }
+
+ // pass any error to the error option
+ if (xhr.status < 200 || xhr.status > 299)
+ {
+ // request error
+ opts.error(index, file, xhr.statusText + " (Server Code " + xhr.status + ")");
+
+ // reset status
+ queue_status = false;
+ } else {
+ // parse response
+ opts.success(index, file, response);
+
+ // upload next file
+ process();
+ }
+ }
+ }
+
+ // return
+ return this;
+ }
+})(jQuery);
\ No newline at end of file
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/style/blue/galaxy.frame.css
--- a/static/style/blue/galaxy.frame.css
+++ b/static/style/blue/galaxy.frame.css
@@ -1,21 +1,33 @@
/*
- galaxy-frames generic styles
+ galaxy generic styles
*/
-.f-corner
+.bs-tooltip
+{
+ z-index: 34010;
+}
+
+.galaxy-corner
{
-moz-border-radius: 4px;
border-radius: 4px;
}
-.f-toggle
+.galaxy-corner-soft
+{
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+}
+
+.galaxy-toggle
{
color: #BCC800;
}
-.bs-tooltip
+.galaxy-shadow
{
- z-index: 34010;
+ -webkit-box-shadow: 1px 1px 4px rgba(0,0,0,0.16);
+ box-shadow: 1px 1px 4px rgba(0,0,0,0.16);
}
/*
@@ -80,42 +92,6 @@
}
/*
- panel active button
-*/
-.galaxy-frame-active
-{
- z-index : 34010;
- position : absolute;
- top : 8px;
- right : 120px;
- cursor : pointer;
- color : #D0D0D0;
-}
-
-/*
- panel load button
-*/
-.galaxy-frame-load
-{
- z-index : 34010;
- position : absolute;
- top : 6px;
- right : 170px;
- cursor : pointer;
- color : #BCC800;
-}
-
-.galaxy-frame-load .number
-{
- position : absolute;
- font-weight : bold;
- font-size : 12px;
- font-family : Verdana, Arial;
- top : 8px;
- left : 26px;
-}
-
-/*
frame components
*/
.galaxy-frame .f-content
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/style/blue/galaxy.master.css
--- /dev/null
+++ b/static/style/blue/galaxy.master.css
@@ -0,0 +1,30 @@
+/*
+ galaxy master
+*/
+.galaxy-master
+{
+ position : absolute;
+ top : 0px;
+ right : 100px;
+ cursor : pointer;
+ color : #D0D0D0;
+ overflow : hidden;
+ z-index : 34010;
+ padding : 8px;
+}
+
+.galaxy-icon
+{
+ float : left;
+ margin : 0px 10px;
+}
+
+.galaxy-icon .number
+{
+ font-weight : bold;
+ font-size : 12px;
+ font-family : Verdana, Arial;
+ position : relative;
+ left : 23px;
+ top : -9px;
+}
\ No newline at end of file
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/style/blue/galaxy.modal.css
--- /dev/null
+++ b/static/style/blue/galaxy.modal.css
@@ -0,0 +1,70 @@
+/*
+ galaxy-modal
+*/
+
+.galaxy-modal
+{
+ z-index : 15000;
+ width : 100%;
+ height : 100%;
+ position : absolute;
+}
+
+.galaxy-modal .background
+{
+ width : 100%;
+ height : 100%;
+ position : absolute;
+ opacity : 0.6;
+ background : #11131A;
+ overflow : auto;
+}
+
+.galaxy-modal .dialog
+{
+ overflow : hidden;
+ position : absolute;
+ background : #FFFFFF;
+ border : 1px solid #D0D0D0;
+ top : 20%;
+ left : 50%;
+ width : 560px;
+ margin-left : -280px;
+ -moz-box-shadow : 0 3px 7px rgba(0, 0, 0, 0.3);
+ box-shadow : 0 3px 7px rgba(0, 0, 0, 0.3);
+ -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+}
+
+.galaxy-modal .header h3
+{
+ margin : 0;
+ line-height : 30px;
+}
+
+.galaxy-modal .header
+{
+ padding : 9px 15px;
+ border-bottom : 1px solid #eee;
+}
+
+.galaxy-modal .body
+{
+ position : relative;
+ overflow-y : auto;
+ max-height : 400px;
+ padding : 15px;
+}
+
+.galaxy-modal .footer
+{
+ text-align : right;
+ border-top : 1px solid #ddd;
+ background-color : #f5f5f5;
+ -webkit-box-shadow : inset 0 1px 0 #ffffff;
+ -moz-box-shadow : inset 0 1px 0 #ffffff;
+ box-shadow : inset 0 1px 0 #ffffff;
+ float : right;
+ padding : 12px;
+ width : 100%;
+ height : 100%;
+}
\ No newline at end of file
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 static/style/blue/galaxy.upload.css
--- /dev/null
+++ b/static/style/blue/galaxy.upload.css
@@ -0,0 +1,97 @@
+/*
+ upload box
+*/
+
+.galaxy-upload-button
+{
+ z-index : 34010;
+ position : absolute;
+ top : 8px;
+ right : 210px;
+ cursor : pointer;
+ color : #D0D0D0;
+}
+
+.galaxy-upload-box
+{
+ margin : -5px;
+ width : 100%;
+ height : 200px;
+ max-height : 200px;
+ border : 1px dashed #D0D0D0;
+ font-weight : bold;
+ line-height : 16px;
+ color : #5C5858;
+ padding : 10px 0px 0px 0px;
+ text-align : center;
+ font-size : 12px;
+ cursor : pointer;
+ overflow : scroll;
+}
+
+.galaxy-upload-highlight
+{
+ border : 1px dashed #5C5858;
+ color : #5C5858;
+}
+
+.galaxy-upload-file
+{
+ position : relative;
+ margin : 5px 20px 5px 20px;
+ border : 1px solid #D0D0D0;
+}
+
+.galaxy-upload-file .title
+{
+ font-weight : normal;
+ font-size : 12px;
+ color : #5C5858;
+ margin : 3px 130px 0px 5px;
+ text-align : left;
+ overflow : hidden;
+}
+
+.galaxy-upload-file .progress-frame
+{
+ border : 0px;
+ margin : 0px 5px 3px 5px;
+ height : 7px;
+ background : #D0D0D0;
+}
+
+.galaxy-upload-file .progress
+{
+ background : #CCFFCC;
+ height : 100%;
+ width : 0%;
+}
+
+.galaxy-upload-file .failed
+{
+ background : #FFCCCC;
+}
+
+.galaxy-upload-file .error
+{
+ font-weight : normal;
+ font-size : 10px;
+ color : #5C5858;
+ text-align : left;
+ overflow : hidden;
+ margin : 0px 5px 0px 5px;
+}
+
+.galaxy-upload-file .info
+{
+ position : absolute;
+ top : 4px;
+ right : 5px;
+ font-weight : normal;
+ font-size : 10px;
+ color : #5C5858;
+ text-align : right;
+ overflow : hidden;
+ max-width : 100px;
+ max-height : 12px;
+}
\ No newline at end of file
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 templates/base/base_panels.mako
--- a/templates/base/base_panels.mako
+++ b/templates/base/base_panels.mako
@@ -101,9 +101,13 @@
}
});
- ## frame manager
- var frame_manager = null;
- require(['galaxy.frame'], function(frame) { this.frame_manager = new frame.GalaxyFrameManager(galaxy_config); });
+ ## load galaxy js-modules
+ require(['galaxy.master', 'galaxy.frame', 'galaxy.upload'], function(master, frame, upload)
+ {
+ Galaxy.master = new master.GalaxyMaster();
+ Galaxy.frame_manager = new frame.GalaxyFrameManager();
+ ##Galaxy.upload = new upload.GalaxyUpload();
+ });
</script></%def>
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 templates/webapps/galaxy/base_panels.mako
--- a/templates/webapps/galaxy/base_panels.mako
+++ b/templates/webapps/galaxy/base_panels.mako
@@ -117,7 +117,7 @@
${tab( "analysis", _("Analyze Data"), h.url_for( controller='/root', action='index' ) )}
## Workflow tab.
- ${tab( "workflow", _("Workflow"), "javascript:frame_manager.frame_new({title: 'Workflow', type: 'url', content: '" + h.url_for( controller='/workflow', action='index' ) + "'});")}
+ ${tab( "workflow", _("Workflow"), "javascript:Galaxy.frame_manager.frame_new({title: 'Workflow', type: 'url', content: '" + h.url_for( controller='/workflow', action='index' ) + "'});")}
## 'Shared Items' or Libraries tab.
<%
@@ -147,10 +147,10 @@
## Visualization menu.
<%
menu_options = [
- [_('New Track Browser'), "javascript:frame_manager.frame_new({title: 'Trackster', type: 'url', content: '" + h.url_for( controller='/visualization', action='trackster' ) + "'});"],
- [_('Saved Visualizations'), "javascript:frame_manager.frame_new({ type: 'url', content : '" + h.url_for( controller='/visualization', action='list' ) + "'});" ]
+ [_('New Track Browser'), "javascript:Galaxy.frame_manager.frame_new({title: 'Trackster', type: 'url', content: '" + h.url_for( controller='/visualization', action='trackster' ) + "'});"],
+ [_('Saved Visualizations'), "javascript:Galaxy.frame_manager.frame_new({ type: 'url', content : '" + h.url_for( controller='/visualization', action='list' ) + "'});" ]
]
- tab( "visualization", _("Visualization"), "javascript:frame_manager.frame_new({title: 'Trackster', type: 'url', content: '" + h.url_for( controller='/visualization', action='list' ) + "'});", menu_options=menu_options )
+ tab( "visualization", _("Visualization"), "javascript:Galaxy.frame_manager.frame_new({title: 'Trackster', type: 'url', content: '" + h.url_for( controller='/visualization', action='list' ) + "'});", menu_options=menu_options )
%>
## Cloud menu.
diff -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 -r 99cc1ee095c39f800ffc8a6bf36912fcd6cd06e9 templates/webapps/galaxy/galaxy.masthead.mako
--- a/templates/webapps/galaxy/galaxy.masthead.mako
+++ b/templates/webapps/galaxy/galaxy.masthead.mako
@@ -33,9 +33,12 @@
if (window != window.top)
$('<link href="' + galaxy_config.root + 'static/style/galaxy.frame.masthead.css" rel="stylesheet">').appendTo('head');
- ## frame manager
- var frame_manager = null;
- require(['galaxy.frame'], function(frame) { this.frame_manager = new frame.GalaxyFrameManager(galaxy_config); });
+ ## load galaxy js-modules
+ require(['galaxy.master', 'galaxy.frame'], function(master, frame)
+ {
+ Galaxy.master = new master.GalaxyMaster();
+ Galaxy.frame_manager = new frame.GalaxyFrameManager();
+ });
</script>
## start main tag
@@ -102,7 +105,7 @@
${tab( "analysis", _("Analyze Data"), h.url_for( controller='/root', action='index' ) )}
## Workflow tab.
- ${tab( "workflow", _("Workflow"), "javascript:frame_manager.frame_new({title: 'Workflow', type: 'url', content: '" + h.url_for( controller='/workflow', action='index' ) + "'});")}
+ ${tab( "workflow", _("Workflow"), "javascript:Galaxy.frame_manager.frame_new({title: 'Workflow', type: 'url', content: '" + h.url_for( controller='/workflow', action='index' ) + "'});")}
## 'Shared Items' or Libraries tab.
<%
@@ -132,10 +135,10 @@
## Visualization menu.
<%
menu_options = [
- [_('New Track Browser'), "javascript:frame_manager.frame_new({title: 'Trackster', type: 'url', content: '" + h.url_for( controller='/visualization', action='trackster' ) + "'});"],
- [_('Saved Visualizations'), "javascript:frame_manager.frame_new({ type: 'url', content : '" + h.url_for( controller='/visualization', action='list' ) + "'});" ]
+ [_('New Track Browser'), "javascript:Galaxy.frame_manager.frame_new({title: 'Trackster', type: 'url', content: '" + h.url_for( controller='/visualization', action='trackster' ) + "'});"],
+ [_('Saved Visualizations'), "javascript:Galaxy.frame_manager.frame_new({ type: 'url', content : '" + h.url_for( controller='/visualization', action='list' ) + "'});" ]
]
- tab( "visualization", _("Visualization"), "javascript:frame_manager.frame_new({title: 'Trackster', type: 'url', content: '" + h.url_for( controller='/visualization', action='list' ) + "'});", menu_options=menu_options )
+ tab( "visualization", _("Visualization"), "javascript:Galaxy.frame_manager.frame_new({title: 'Trackster', type: 'url', content: '" + h.url_for( controller='/visualization', action='list' ) + "'});", menu_options=menu_options )
%>
## Cloud menu.
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: jmchilton: Add ucsc_tools requirement for extract_genomic_dna.xml tool.
by commits-noreply@bitbucket.org 11 Sep '13
by commits-noreply@bitbucket.org 11 Sep '13
11 Sep '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/598d633c9caa/
Changeset: 598d633c9caa
User: jmchilton
Date: 2013-09-03 19:32:02
Summary: Add ucsc_tools requirement for extract_genomic_dna.xml tool.
Affected #: 1 file
diff -r fd380581d0073c6a08cca74e34434f058804de3d -r 598d633c9caa9cccbd28e8fc57f650c1b8564371 tools/extract/extract_genomic_dna.xml
--- a/tools/extract/extract_genomic_dna.xml
+++ b/tools/extract/extract_genomic_dna.xml
@@ -53,6 +53,7 @@
</outputs><requirements><requirement type="binary">faToTwoBit</requirement>
+ <requirement type="package">ucsc_tools</requirement></requirements><tests><test>
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: Dave Bouvier: Fix for displaying repository dependencies that are not filtered out.
by commits-noreply@bitbucket.org 10 Sep '13
by commits-noreply@bitbucket.org 10 Sep '13
10 Sep '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/fd380581d007/
Changeset: fd380581d007
User: Dave Bouvier
Date: 2013-09-10 22:35:48
Summary: Fix for displaying repository dependencies that are not filtered out.
Affected #: 1 file
diff -r cd91ec8f14059167cdfda2ab606035c97ead5469 -r fd380581d0073c6a08cca74e34434f058804de3d lib/tool_shed/util/repository_dependency_util.py
--- a/lib/tool_shed/util/repository_dependency_util.py
+++ b/lib/tool_shed/util/repository_dependency_util.py
@@ -625,10 +625,7 @@
tool_shed, name, owner, changeset_revision, prior_installation_required, only_if_compiling_contained_td = \
common_util.parse_repository_dependency_tuple( required_rd_tup )
if not asbool( only_if_compiling_contained_td ):
- if rd_key in filtered_key_rd_dict:
- filtered_key_rd_dict[ rd_key ].append( required_rd_tup )
- else:
- filtered_key_rd_dict[ rd_key ] = [ required_rd_tup ]
+ filtered_key_rd_dict[ rd_key ] = required_rd_tup
return filtered_key_rd_dict
def merge_missing_repository_dependencies_to_installed_container( containers_dict ):
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: Dave Bouvier: Fix for filtering out repository dependencies that are only required when compiling a tool dependency because the precompiled binary was not found or failed to install.
by commits-noreply@bitbucket.org 10 Sep '13
by commits-noreply@bitbucket.org 10 Sep '13
10 Sep '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/cd91ec8f1405/
Changeset: cd91ec8f1405
User: Dave Bouvier
Date: 2013-09-10 20:35:06
Summary: Fix for filtering out repository dependencies that are only required when compiling a tool dependency because the precompiled binary was not found or failed to install.
Affected #: 1 file
diff -r 595c30bc8df5dfd626d78cc4e030ac1910b54f4e -r cd91ec8f14059167cdfda2ab606035c97ead5469 lib/tool_shed/util/repository_dependency_util.py
--- a/lib/tool_shed/util/repository_dependency_util.py
+++ b/lib/tool_shed/util/repository_dependency_util.py
@@ -678,7 +678,7 @@
current_repository_key_rd_dicts = get_updated_changeset_revisions_for_repository_dependencies( trans, current_repository_key_rd_dicts )
for key_rd_dict in current_repository_key_rd_dicts:
# Filter out repository dependencies that are required only if compiling the dependent repository's tool dependency.
- all_repository_dependencieskey_rd_dict = filter_only_if_compiling_contained_td( key_rd_dict )
+ key_rd_dict = filter_only_if_compiling_contained_td( key_rd_dict )
if key_rd_dict:
is_circular = False
if not in_key_rd_dicts( key_rd_dict, handled_key_rd_dicts ) and not in_key_rd_dicts( key_rd_dict, key_rd_dicts_to_be_processed ):
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: Slight refactoring of message generation in the tool shed.
by commits-noreply@bitbucket.org 10 Sep '13
by commits-noreply@bitbucket.org 10 Sep '13
10 Sep '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/595c30bc8df5/
Changeset: 595c30bc8df5
User: greg
Date: 2013-09-10 20:19:46
Summary: Slight refactoring of message generation in the tool shed.
Affected #: 5 files
diff -r 04a3137539d245fa294f73f8b6467a5b13e6d028 -r 595c30bc8df5dfd626d78cc4e030ac1910b54f4e lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -2159,11 +2159,17 @@
all_repository_dependencies=None,
handled_key_rd_dicts=None )
if str( repository.type ) != rt_util.TOOL_DEPENDENCY_DEFINITION:
- # Handle messaging for orphan tool dependencies.
- orphan_message = tool_dependency_util.generate_message_for_orphan_tool_dependencies( trans, repository, metadata )
- if orphan_message:
- message += orphan_message
+ # Handle messaging for resetting repository type to the optimal value.
+ change_repository_type_message = tool_dependency_util.generate_message_for_repository_type_change( trans, repository )
+ if change_repository_type_message:
+ message += change_repository_type_message
status = 'warning'
+ else:
+ # Handle messaging for orphan tool dependency definitions.
+ orphan_message = tool_dependency_util.generate_message_for_orphan_tool_dependencies( trans, repository, metadata )
+ if orphan_message:
+ message += orphan_message
+ status = 'warning'
if is_malicious:
if trans.app.security_agent.can_push( trans.app, trans.user, repository ):
message += malicious_error_can_push
diff -r 04a3137539d245fa294f73f8b6467a5b13e6d028 -r 595c30bc8df5dfd626d78cc4e030ac1910b54f4e lib/galaxy/webapps/tool_shed/controllers/upload.py
--- a/lib/galaxy/webapps/tool_shed/controllers/upload.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/upload.py
@@ -207,15 +207,20 @@
else:
metadata_dict = {}
if str( repository.type ) != rt_util.TOOL_DEPENDENCY_DEFINITION:
- # Provide a warning message if a tool_dependencies.xml file is provided, but tool dependencies weren't loaded due to a requirement tag mismatch
- # or some other problem. Tool dependency definitions can define orphan tool dependencies (no relationship to any tools contained in the repository),
- # so warning messages are important because orphans are always valid. The repository owner must be warned in case they did not intend to define an
- # orphan dependency, but simply provided incorrect information (tool shed, name owner, changeset_revision) for the definition.
- # Handle messaging for orphan tool dependencies.
- orphan_message = tool_dependency_util.generate_message_for_orphan_tool_dependencies( trans, repository, metadata_dict )
- if orphan_message:
- message += orphan_message
+ change_repository_type_message = tool_dependency_util.generate_message_for_repository_type_change( trans, repository )
+ if change_repository_type_message:
+ message += change_repository_type_message
status = 'warning'
+ else:
+ # Provide a warning message if a tool_dependencies.xml file is provided, but tool dependencies weren't loaded due to a requirement tag mismatch
+ # or some other problem. Tool dependency definitions can define orphan tool dependencies (no relationship to any tools contained in the repository),
+ # so warning messages are important because orphans are always valid. The repository owner must be warned in case they did not intend to define an
+ # orphan dependency, but simply provided incorrect information (tool shed, name owner, changeset_revision) for the definition.
+ # Handle messaging for orphan tool dependencies.
+ orphan_message = tool_dependency_util.generate_message_for_orphan_tool_dependencies( trans, repository, metadata_dict )
+ if orphan_message:
+ message += orphan_message
+ status = 'warning'
# Handle messaging for invalid tool dependencies.
invalid_tool_dependencies_message = tool_dependency_util.generate_message_for_invalid_tool_dependencies( metadata_dict )
if invalid_tool_dependencies_message:
diff -r 04a3137539d245fa294f73f8b6467a5b13e6d028 -r 595c30bc8df5dfd626d78cc4e030ac1910b54f4e lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -906,13 +906,13 @@
repository_dependency_tups=invalid_repository_dependency_tups,
is_valid=False,
description=description )
- # We need to continue to restrict the behavior of orphan tool dependencies, possibly eliminating them altoghether at some point.
+ # We need to continue to restrict the behavior for defining orphan tool dependencies, possibly eliminating them altoghether at some point.
check_for_orphan_tool_dependencies = False
if app.name == 'tool_shed':
- if repository.type == rt_util.UNRESTRICTED and 'tools' not in metadata_dict:
+ if repository.type != rt_util.TOOL_DEPENDENCY_DEFINITION and not repository.can_change_type_to( app, rt_util.TOOL_DEPENDENCY_DEFINITION ):
check_for_orphan_tool_dependencies = True
- elif 'tools' in metadata_dict:
- check_for_orphan_tool_dependencies = True
+ elif 'tools' in metadata_dict:
+ check_for_orphan_tool_dependencies = True
if check_for_orphan_tool_dependencies:
# Determine and store orphan tool dependencies.
orphan_tool_dependencies = get_orphan_tool_dependencies( metadata_dict )
diff -r 04a3137539d245fa294f73f8b6467a5b13e6d028 -r 595c30bc8df5dfd626d78cc4e030ac1910b54f4e lib/tool_shed/util/tool_dependency_util.py
--- a/lib/tool_shed/util/tool_dependency_util.py
+++ b/lib/tool_shed/util/tool_dependency_util.py
@@ -150,14 +150,17 @@
version = requirements_dict[ 'version' ]
message += "<b>* name:</b> %s, <b>type:</b> %s, <b>version:</b> %s<br/>" % ( str( name ), str( type ), str( version ) )
message += "<br/>"
- elif repository.can_change_type_to( trans.app, rt_util.TOOL_DEPENDENCY_DEFINITION ):
- tool_dependency_definition_type_class = trans.app.repository_types_registry.get_class_by_label( rt_util.TOOL_DEPENDENCY_DEFINITION )
- message += "This repository currently contains a single file named <b>%s</b>. If additional files will " % suc.TOOL_DEPENDENCY_DEFINITION_FILENAME
- message += "not be added to this repository, then it's type should be set to <b>%s</b>.<br/>" % tool_dependency_definition_type_class.label
- else:
- message += "This repository contains no tools, so it's defined tool dependencies are considered orphans within this repository.<br/>"
return message
+def generate_message_for_repository_type_change( trans, repository ):
+ message = ''
+ if repository.can_change_type_to( trans.app, rt_util.TOOL_DEPENDENCY_DEFINITION ):
+ tool_dependency_definition_type_class = trans.app.repository_types_registry.get_class_by_label( rt_util.TOOL_DEPENDENCY_DEFINITION )
+ message += "This repository currently contains a single file named <b>%s</b>. If additional files will " % suc.TOOL_DEPENDENCY_DEFINITION_FILENAME
+ message += "not be added to this repository, then it's type should be set to <b>%s</b>.<br/>" % tool_dependency_definition_type_class.label
+ return message
+
+
def get_download_url_for_platform( url_templates, platform_info_dict ):
'''
Compare the dict returned by get_platform_info() with the values specified in the url_template element. Return
diff -r 04a3137539d245fa294f73f8b6467a5b13e6d028 -r 595c30bc8df5dfd626d78cc4e030ac1910b54f4e test/tool_shed/functional/test_0100_complex_repository_dependencies.py
--- a/test/tool_shed/functional/test_0100_complex_repository_dependencies.py
+++ b/test/tool_shed/functional/test_0100_complex_repository_dependencies.py
@@ -54,7 +54,7 @@
strings_displayed=[ 'This repository currently contains a single file named <b>tool_dependencies.xml</b>' ],
strings_not_displayed=[] )
# Visit the manage repository page for package_bwa_0_5_9_0100.
- self.display_manage_repository_page( repository, strings_displayed=[ 'Tool dependencies', 'may not be', 'in this repository' ] )
+ self.display_manage_repository_page( repository, strings_displayed=[ 'Tool dependencies', 'will not be', 'to this repository' ] )
def test_0010_create_bwa_base_repository( self ):
'''Create and populate bwa_base_0100.'''
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: Don't generate error messages when resetting metadata on installed tool shed repositories that have repository dependencies that are not installed because they were not needed for compiling the dependent repository's tool dependency.
by commits-noreply@bitbucket.org 10 Sep '13
by commits-noreply@bitbucket.org 10 Sep '13
10 Sep '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/04a3137539d2/
Changeset: 04a3137539d2
User: greg
Date: 2013-09-10 19:29:18
Summary: Don't generate error messages when resetting metadata on installed tool shed repositories that have repository dependencies that are not installed because they were not needed for compiling the dependent repository's tool dependency.
Affected #: 1 file
diff -r 1e30cdb6d3b82a68da8daddc86411eecc33be444 -r 04a3137539d245fa294f73f8b6467a5b13e6d028 lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -1195,14 +1195,17 @@
repository = suc.get_repository_for_dependency_relationship( app, cleaned_toolshed, name, owner, updated_changeset_revision )
if repository:
return repository_dependency_tup, is_valid, error_message
- # We'll currently default to setting the repository dependency definition as invalid if an installed repository cannot be found.
- # This may not be ideal because the tool shed may have simply been inaccessible when metadata was being generated for the installed
- # tool shed repository.
- error_message = "Ignoring invalid repository dependency definition for tool shed %s, name %s, owner %s, changeset revision %s "% \
- ( toolshed, name, owner, changeset_revision )
- log.debug( error_message )
- is_valid = False
- return repository_dependency_tup, is_valid, error_message
+ # Don't generate an error message for missing repository dependencies that are required only if compiling the dependent repository's
+ # tool dependency.
+ if not only_if_compiling_contained_td:
+ # We'll currently default to setting the repository dependency definition as invalid if an installed repository cannot be found.
+ # This may not be ideal because the tool shed may have simply been inaccessible when metadata was being generated for the installed
+ # tool shed repository.
+ error_message = "Ignoring invalid repository dependency definition for tool shed %s, name %s, owner %s, changeset revision %s "% \
+ ( toolshed, name, owner, changeset_revision )
+ log.debug( error_message )
+ is_valid = False
+ return repository_dependency_tup, is_valid, error_message
else:
# We're in the tool shed.
if suc.tool_shed_is_this_tool_shed( toolshed ):
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
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0bc38956530a/
Changeset: 0bc38956530a
Branch: dataset-cleanup
User: lance_parsons
Date: 2013-04-18 17:24:09
Summary: Basic administrative dataset cleanup script
Affected #: 3 files
diff -r 18b23ed8de5b384f142db349e7379c03567758df -r 0bc38956530a382faea4b42e771037672c2a6b0c scripts/cleanup_datasets/admin_cleanup_datasets.py
--- /dev/null
+++ b/scripts/cleanup_datasets/admin_cleanup_datasets.py
@@ -0,0 +1,256 @@
+#!/usr/bin/env python
+"""
+Mark datasets as deleted that are older than specified cutoff
+and (optionaly) with a tool_id that matches the specified search
+string.
+
+This script is useful for administrators to cleanup after users who
+leave many old datasets around. It was modeled after the cleanup_datasets.py
+script originally distributed with Galaxy.
+
+Basic Usage:
+ admin_cleanup_datasets.py universe_wsgi.ini -d 60 \
+ --template=email_template.txt
+
+Required Arguments:
+ config_file - the Galaxy configuration file (universe_wsgi.ini)
+
+Optional Arguments:
+ -d --days - number of days old the dataset must be (default: 60)
+ --tool_id - string to search for in dataset tool_id
+ --template - Mako template file to use for email notification
+ -i --info_only - Print results, but don't email or delete anything
+ -e --email_only - Email notifications, but don't delete anything
+ Useful for notifying users of pending deletion
+
+ --smtp - Specify smtp server
+ If not specified, use smtp settings specified in config file
+ --fromaddr - Specify from address
+ If not specified, use error_email_to specified in config file
+
+Email Template Variables:
+ cutoff - the cutoff in days
+ email - the users email address
+ datasets - a list of tuples containing 'dataset' and 'history' names
+
+
+Author: Lance Parsons (lparsons(a)princeton.edu)
+"""
+import os
+import sys
+import shutil
+import logging
+from collections import defaultdict
+
+log = logging.getLogger()
+log.setLevel(10)
+log.addHandler(logging.StreamHandler(sys.stdout))
+
+from cleanup_datasets import CleanupDatasetsApplication
+import pkg_resources
+pkg_resources.require("SQLAlchemy >= 0.4")
+
+#pkg_resources.require("Mako")
+from mako.template import Template
+
+import time
+import ConfigParser
+from datetime import datetime, timedelta
+from time import strftime
+from optparse import OptionParser
+
+import galaxy.config
+import galaxy.model.mapping
+import sqlalchemy as sa
+from galaxy.model.orm import and_
+import galaxy.util
+
+assert sys.version_info[:2] >= (2, 4)
+
+
+def main():
+ """
+ Datasets that are older than the specified cutoff and for which the tool_id
+ contains the specified text will be marked as deleted in user's history and
+ the user will be notified by email using the specified template file.
+ """
+ parser = OptionParser()
+ parser.add_option("-d", "--days", dest="days", action="store",
+ type="int", help="number of days (60)", default=60)
+ parser.add_option("--tool_id", default="",
+ help="Text to match against tool_id")
+ parser.add_option("--template", default=None,
+ help="Mako Template file to use as email "
+ "Variables are 'cutoff' for the cutoff in days, "
+ "'email' for users email and "
+ "'datasets' which is a list of tuples "
+ "containing 'dataset' and 'history' names. "
+ "Default: admin_cleanup_deletion_template.txt")
+ parser.add_option("-i", "--info_only", action="store_true",
+ dest="info_only", help="info about the requested action",
+ default=False)
+ parser.add_option("-e", "--email_only", action="store_true",
+ dest="email_only", help="Send emails only, don't delete",
+ default=False)
+ parser.add_option("--smtp", default=None,
+ help="SMTP Server to use to send email. "
+ "Default: [read from galaxy ini file]")
+ parser.add_option("--fromaddr", default=None,
+ help="From address to use to send email. "
+ "Default: [read from galaxy ini file]")
+ (options, args) = parser.parse_args()
+ ini_file = args[0]
+
+ config_parser = ConfigParser.ConfigParser({'here': os.getcwd()})
+ config_parser.read(ini_file)
+ config_dict = {}
+ for key, value in config_parser.items("app:main"):
+ config_dict[key] = value
+
+ if options.smtp is not None:
+ config_dict['smtp_server'] = options.smtp
+ if config_dict.get('smtp_server') is None:
+ parser.error("SMTP Server must be specified as an option (--smtp) "
+ "or in the config file (smtp_server)")
+
+ if options.fromaddr is not None:
+ config_dict['error_email_to'] = options.fromaddr
+ if config_dict.get('error_email_to') is None:
+ parser.error("From address must be specified as an option "
+ "(--fromaddr) or in the config file "
+ "(error_email_to)")
+
+ scriptdir = os.path.dirname(os.path.abspath(__file__))
+ template_file = options.template
+ if template_file is None:
+ default_template = os.path.join(scriptdir,
+ 'admin_cleanup_deletion_template.txt')
+ sample_template_file = "%s.sample" % default_template
+ if os.path.exists(default_template):
+ template_file = default_template
+ elif os.path.exists(sample_template_file):
+ print "Copying %s to %s" % (sample_template_file, default_template)
+ shutil.copyfile(sample_template_file, default_template)
+ template_file = default_template
+ else:
+ parser.error("Default template (%s) or sample template (%s) not "
+ "found, please specify template as an option "
+ "(--template)." % default_template,
+ sample_template_file)
+ elif not os.path.exists(template_file):
+ parser.error("Specified template file (%s) not found." % template_file)
+
+ config = galaxy.config.Configuration(**config_dict)
+
+ app = CleanupDatasetsApplication(config)
+ cutoff_time = datetime.utcnow() - timedelta(days=options.days)
+ now = strftime("%Y-%m-%d %H:%M:%S")
+
+ print "##########################################"
+ print "\n# %s - Handling stuff older than %i days" % (now, options.days)
+
+ if options.info_only:
+ print "# Displaying info only ( --info_only )\n"
+ elif options.email_only:
+ print "# Sending emails only, not deleting ( --email_only )\n"
+
+ administrative_delete_datasets(
+ app, cutoff_time, options.days, tool_id=options.tool_id,
+ template_file=template_file, config=config,
+ email_only=options.email_only, info_only=options.info_only)
+ app.shutdown()
+ sys.exit(0)
+
+
+def administrative_delete_datasets(app, cutoff_time, cutoff_days,
+ tool_id, template_file,
+ config, email_only=False,
+ info_only=False):
+ # Marks dataset history association deleted and email users
+ start = time.time()
+ # We really only need the id column here, but sqlalchemy barfs when
+ # trying to select only 1 column
+ hda_ids_query = sa.select(
+ (app.model.HistoryDatasetAssociation.table.c.id,
+ app.model.HistoryDatasetAssociation.table.c.deleted),
+ whereclause=and_(
+ app.model.Dataset.table.c.deleted == False,
+ app.model.HistoryDatasetAssociation.table.c.update_time
+ < cutoff_time,
+ app.model.Job.table.c.tool_id.like("%%%s%%" % tool_id),
+ app.model.HistoryDatasetAssociation.table.c.deleted == False),
+ from_obj=[sa.outerjoin(
+ app.model.Dataset.table,
+ app.model.HistoryDatasetAssociation.table)
+ .outerjoin(app.model.JobToOutputDatasetAssociation.table)
+ .outerjoin(app.model.Job.table)])
+ deleted_instance_count = 0
+ # skip = []
+ user_notifications = defaultdict(list)
+ # Add all datasets associated with Histories to our list
+ hda_ids = []
+ hda_ids.extend(
+ [row.id for row in hda_ids_query.execute()])
+ # Process each of the Dataset objects
+ for hda_id in hda_ids:
+ user_query = sa.select(
+ [app.model.HistoryDatasetAssociation.table,
+ app.model.History.table,
+ app.model.User.table],
+ whereclause=and_(
+ app.model.HistoryDatasetAssociation.table.c.id == hda_id),
+ from_obj=[sa.join(app.model.User.table,
+ app.model.History.table)
+ .join(app.model.HistoryDatasetAssociation.table)],
+ use_labels=True)
+ for result in user_query.execute():
+ user_notifications[result[app.model.User.table.c.email]].append(
+ (result[app.model.HistoryDatasetAssociation.table.c.name],
+ result[app.model.History.table.c.name]))
+ deleted_instance_count += 1
+ if not info_only and not email_only:
+ # Get the HistoryDatasetAssociation objects
+ hda = app.sa_session.query(
+ app.model.HistoryDatasetAssociation).get(hda_id)
+ if not hda.deleted:
+ # Mark the HistoryDatasetAssociation as deleted
+ hda.deleted = True
+ app.sa_session.add(hda)
+ print ("Marked HistoryDatasetAssociation id %d as "
+ "deleted" % hda.id)
+ app.sa_session.flush()
+
+ emailtemplate = Template(filename=template_file)
+ for (email, dataset_list) in user_notifications.iteritems():
+ msgtext = emailtemplate.render(email=email,
+ datasets=dataset_list,
+ cutoff=cutoff_days)
+ subject = "Galaxy Server Cleanup " \
+ "- %d datasets DELETED" % len(dataset_list)
+ fromaddr = config.error_email_to
+ print ""
+ print "From: %s" % fromaddr
+ print "To: %s" % email
+ print "Subject: %s" % subject
+ print "----------"
+ print msgtext
+ if not info_only:
+ #msg = MIMEText(msgtext)
+ #msg['Subject'] = subject
+ #msg['From'] = 'noone(a)nowhere.com'
+ #msg['To'] = email
+ galaxy.util.send_mail(fromaddr, email, subject,
+ msgtext, config)
+ #s = smtplib.SMTP(smtp_server)
+ #s.sendmail(['lparsons(a)princeton.edu'], email, msg.as_string())
+ #s.quit()
+
+ stop = time.time()
+ print ""
+ print "Marked %d dataset instances as deleted" % deleted_instance_count
+ print "Total elapsed time: ", stop - start
+ print "##########################################"
+
+
+if __name__ == "__main__":
+ main()
diff -r 18b23ed8de5b384f142db349e7379c03567758df -r 0bc38956530a382faea4b42e771037672c2a6b0c scripts/cleanup_datasets/admin_cleanup_deletion_template.txt.sample
--- /dev/null
+++ b/scripts/cleanup_datasets/admin_cleanup_deletion_template.txt.sample
@@ -0,0 +1,11 @@
+Galaxy Server Cleanup
+---------------------
+The following datasets you own on Galaxy are older than ${cutoff} days and have been DELETED:
+
+% for dataset, history in datasets:
+ "${dataset}" in history "${history}"
+% endfor
+
+You may be able to undelete them by logging into Galaxy, navigating to the appropriate history, selecting "Include Deleted Datasets" from the history options menu, and clicking on the link to undelete each dataset that you want to keep. You can then download the datasets. Thank you for your understanding and cooporation in this necessary cleanup in order to keep the Galaxy resource available. Please don't hesitate to contact us if you have any questions.
+
+ -- Galaxy Administrators
diff -r 18b23ed8de5b384f142db349e7379c03567758df -r 0bc38956530a382faea4b42e771037672c2a6b0c scripts/cleanup_datasets/admin_cleanup_warning_template.txt.sample
--- /dev/null
+++ b/scripts/cleanup_datasets/admin_cleanup_warning_template.txt.sample
@@ -0,0 +1,11 @@
+Galaxy Server Cleanup
+---------------------
+The following datasets you own on Galaxy are older than ${cutoff} days and will be deleted soon. Be sure to download any datasets you need to keep.
+
+% for dataset, history in datasets:
+ "${dataset}" in history "${history}"
+% endfor
+
+Please contact us if you have any questions.
+
+ -- Galaxy Administrators
https://bitbucket.org/galaxy/galaxy-central/commits/e4734c99812a/
Changeset: e4734c99812a
Branch: dataset-cleanup
User: lance_parsons
Date: 2013-04-18 21:43:00
Summary: Fix admin_cleanup_datasets.py for copied datasets
Affected #: 1 file
diff -r 0bc38956530a382faea4b42e771037672c2a6b0c -r e4734c99812ad2f240b2fa963ea9af3fa710bd74 scripts/cleanup_datasets/admin_cleanup_datasets.py
--- a/scripts/cleanup_datasets/admin_cleanup_datasets.py
+++ b/scripts/cleanup_datasets/admin_cleanup_datasets.py
@@ -17,7 +17,7 @@
Optional Arguments:
-d --days - number of days old the dataset must be (default: 60)
- --tool_id - string to search for in dataset tool_id
+ --tool_id - string to search for in dataset tool_id (default: all)
--template - Mako template file to use for email notification
-i --info_only - Print results, but don't email or delete anything
-e --email_only - Email notifications, but don't delete anything
@@ -47,8 +47,8 @@
log.addHandler(logging.StreamHandler(sys.stdout))
from cleanup_datasets import CleanupDatasetsApplication
-import pkg_resources
-pkg_resources.require("SQLAlchemy >= 0.4")
+#import pkg_resources
+#pkg_resources.require("SQLAlchemy >= 0.4")
#pkg_resources.require("Mako")
from mako.template import Template
@@ -77,8 +77,9 @@
parser = OptionParser()
parser.add_option("-d", "--days", dest="days", action="store",
type="int", help="number of days (60)", default=60)
- parser.add_option("--tool_id", default="",
- help="Text to match against tool_id")
+ parser.add_option("--tool_id", default=None,
+ help="Text to match against tool_id"
+ "Default: match all")
parser.add_option("--template", default=None,
help="Mako Template file to use as email "
"Variables are 'cutoff' for the cutoff in days, "
@@ -168,6 +169,7 @@
info_only=False):
# Marks dataset history association deleted and email users
start = time.time()
+ # Get HDAs older than cutoff time (ignore tool_id at this point)
# We really only need the id column here, but sqlalchemy barfs when
# trying to select only 1 column
hda_ids_query = sa.select(
@@ -177,20 +179,28 @@
app.model.Dataset.table.c.deleted == False,
app.model.HistoryDatasetAssociation.table.c.update_time
< cutoff_time,
- app.model.Job.table.c.tool_id.like("%%%s%%" % tool_id),
app.model.HistoryDatasetAssociation.table.c.deleted == False),
from_obj=[sa.outerjoin(
app.model.Dataset.table,
- app.model.HistoryDatasetAssociation.table)
- .outerjoin(app.model.JobToOutputDatasetAssociation.table)
- .outerjoin(app.model.Job.table)])
- deleted_instance_count = 0
- # skip = []
- user_notifications = defaultdict(list)
- # Add all datasets associated with Histories to our list
+ app.model.HistoryDatasetAssociation.table)])
+
+ # Add all datasets associated with Histories to our list
hda_ids = []
hda_ids.extend(
[row.id for row in hda_ids_query.execute()])
+
+ # Now find the tool_id that generated the dataset (even if it was copied)
+ tool_matched_ids = []
+ if tool_id is not None:
+ for hda_id in hda_ids:
+ this_tool_id = _get_tool_id_for_hda(app, hda_id)
+ if this_tool_id is not None and tool_id in this_tool_id:
+ tool_matched_ids.append(hda_id)
+ hda_ids = tool_matched_ids
+
+ deleted_instance_count = 0
+ user_notifications = defaultdict(list)
+
# Process each of the Dataset objects
for hda_id in hda_ids:
user_query = sa.select(
@@ -252,5 +262,22 @@
print "##########################################"
+def _get_tool_id_for_hda(app, hda_id):
+ # TODO Some datasets don't seem to have an entry in jtod or a copied_from
+ if hda_id is None:
+ return None
+ job = app.sa_session.query(app.model.Job).\
+ join(app.model.JobToOutputDatasetAssociation).\
+ filter(app.model.JobToOutputDatasetAssociation.table.c.dataset_id ==
+ hda_id).first()
+ if job is not None:
+ return job.tool_id
+ else:
+ hda = app.sa_session.query(app.model.HistoryDatasetAssociation).\
+ get(hda_id)
+ return _get_tool_id_for_hda(app, hda.
+ copied_from_history_dataset_association_id)
+
+
if __name__ == "__main__":
main()
https://bitbucket.org/galaxy/galaxy-central/commits/1e30cdb6d3b8/
Changeset: 1e30cdb6d3b8
User: dannon
Date: 2013-09-10 19:14:10
Summary: Merged in lance_parsons/galaxy-central-pull-requests/dataset-cleanup (pull request #158)
Basic administrative dataset cleanup script
Affected #: 3 files
diff -r 69bec229bdf85900f7d581e735aa69ee2cc2aeb9 -r 1e30cdb6d3b82a68da8daddc86411eecc33be444 scripts/cleanup_datasets/admin_cleanup_datasets.py
--- /dev/null
+++ b/scripts/cleanup_datasets/admin_cleanup_datasets.py
@@ -0,0 +1,283 @@
+#!/usr/bin/env python
+"""
+Mark datasets as deleted that are older than specified cutoff
+and (optionaly) with a tool_id that matches the specified search
+string.
+
+This script is useful for administrators to cleanup after users who
+leave many old datasets around. It was modeled after the cleanup_datasets.py
+script originally distributed with Galaxy.
+
+Basic Usage:
+ admin_cleanup_datasets.py universe_wsgi.ini -d 60 \
+ --template=email_template.txt
+
+Required Arguments:
+ config_file - the Galaxy configuration file (universe_wsgi.ini)
+
+Optional Arguments:
+ -d --days - number of days old the dataset must be (default: 60)
+ --tool_id - string to search for in dataset tool_id (default: all)
+ --template - Mako template file to use for email notification
+ -i --info_only - Print results, but don't email or delete anything
+ -e --email_only - Email notifications, but don't delete anything
+ Useful for notifying users of pending deletion
+
+ --smtp - Specify smtp server
+ If not specified, use smtp settings specified in config file
+ --fromaddr - Specify from address
+ If not specified, use error_email_to specified in config file
+
+Email Template Variables:
+ cutoff - the cutoff in days
+ email - the users email address
+ datasets - a list of tuples containing 'dataset' and 'history' names
+
+
+Author: Lance Parsons (lparsons(a)princeton.edu)
+"""
+import os
+import sys
+import shutil
+import logging
+from collections import defaultdict
+
+log = logging.getLogger()
+log.setLevel(10)
+log.addHandler(logging.StreamHandler(sys.stdout))
+
+from cleanup_datasets import CleanupDatasetsApplication
+#import pkg_resources
+#pkg_resources.require("SQLAlchemy >= 0.4")
+
+#pkg_resources.require("Mako")
+from mako.template import Template
+
+import time
+import ConfigParser
+from datetime import datetime, timedelta
+from time import strftime
+from optparse import OptionParser
+
+import galaxy.config
+import galaxy.model.mapping
+import sqlalchemy as sa
+from galaxy.model.orm import and_
+import galaxy.util
+
+assert sys.version_info[:2] >= (2, 4)
+
+
+def main():
+ """
+ Datasets that are older than the specified cutoff and for which the tool_id
+ contains the specified text will be marked as deleted in user's history and
+ the user will be notified by email using the specified template file.
+ """
+ parser = OptionParser()
+ parser.add_option("-d", "--days", dest="days", action="store",
+ type="int", help="number of days (60)", default=60)
+ parser.add_option("--tool_id", default=None,
+ help="Text to match against tool_id"
+ "Default: match all")
+ parser.add_option("--template", default=None,
+ help="Mako Template file to use as email "
+ "Variables are 'cutoff' for the cutoff in days, "
+ "'email' for users email and "
+ "'datasets' which is a list of tuples "
+ "containing 'dataset' and 'history' names. "
+ "Default: admin_cleanup_deletion_template.txt")
+ parser.add_option("-i", "--info_only", action="store_true",
+ dest="info_only", help="info about the requested action",
+ default=False)
+ parser.add_option("-e", "--email_only", action="store_true",
+ dest="email_only", help="Send emails only, don't delete",
+ default=False)
+ parser.add_option("--smtp", default=None,
+ help="SMTP Server to use to send email. "
+ "Default: [read from galaxy ini file]")
+ parser.add_option("--fromaddr", default=None,
+ help="From address to use to send email. "
+ "Default: [read from galaxy ini file]")
+ (options, args) = parser.parse_args()
+ ini_file = args[0]
+
+ config_parser = ConfigParser.ConfigParser({'here': os.getcwd()})
+ config_parser.read(ini_file)
+ config_dict = {}
+ for key, value in config_parser.items("app:main"):
+ config_dict[key] = value
+
+ if options.smtp is not None:
+ config_dict['smtp_server'] = options.smtp
+ if config_dict.get('smtp_server') is None:
+ parser.error("SMTP Server must be specified as an option (--smtp) "
+ "or in the config file (smtp_server)")
+
+ if options.fromaddr is not None:
+ config_dict['error_email_to'] = options.fromaddr
+ if config_dict.get('error_email_to') is None:
+ parser.error("From address must be specified as an option "
+ "(--fromaddr) or in the config file "
+ "(error_email_to)")
+
+ scriptdir = os.path.dirname(os.path.abspath(__file__))
+ template_file = options.template
+ if template_file is None:
+ default_template = os.path.join(scriptdir,
+ 'admin_cleanup_deletion_template.txt')
+ sample_template_file = "%s.sample" % default_template
+ if os.path.exists(default_template):
+ template_file = default_template
+ elif os.path.exists(sample_template_file):
+ print "Copying %s to %s" % (sample_template_file, default_template)
+ shutil.copyfile(sample_template_file, default_template)
+ template_file = default_template
+ else:
+ parser.error("Default template (%s) or sample template (%s) not "
+ "found, please specify template as an option "
+ "(--template)." % default_template,
+ sample_template_file)
+ elif not os.path.exists(template_file):
+ parser.error("Specified template file (%s) not found." % template_file)
+
+ config = galaxy.config.Configuration(**config_dict)
+
+ app = CleanupDatasetsApplication(config)
+ cutoff_time = datetime.utcnow() - timedelta(days=options.days)
+ now = strftime("%Y-%m-%d %H:%M:%S")
+
+ print "##########################################"
+ print "\n# %s - Handling stuff older than %i days" % (now, options.days)
+
+ if options.info_only:
+ print "# Displaying info only ( --info_only )\n"
+ elif options.email_only:
+ print "# Sending emails only, not deleting ( --email_only )\n"
+
+ administrative_delete_datasets(
+ app, cutoff_time, options.days, tool_id=options.tool_id,
+ template_file=template_file, config=config,
+ email_only=options.email_only, info_only=options.info_only)
+ app.shutdown()
+ sys.exit(0)
+
+
+def administrative_delete_datasets(app, cutoff_time, cutoff_days,
+ tool_id, template_file,
+ config, email_only=False,
+ info_only=False):
+ # Marks dataset history association deleted and email users
+ start = time.time()
+ # Get HDAs older than cutoff time (ignore tool_id at this point)
+ # We really only need the id column here, but sqlalchemy barfs when
+ # trying to select only 1 column
+ hda_ids_query = sa.select(
+ (app.model.HistoryDatasetAssociation.table.c.id,
+ app.model.HistoryDatasetAssociation.table.c.deleted),
+ whereclause=and_(
+ app.model.Dataset.table.c.deleted == False,
+ app.model.HistoryDatasetAssociation.table.c.update_time
+ < cutoff_time,
+ app.model.HistoryDatasetAssociation.table.c.deleted == False),
+ from_obj=[sa.outerjoin(
+ app.model.Dataset.table,
+ app.model.HistoryDatasetAssociation.table)])
+
+ # Add all datasets associated with Histories to our list
+ hda_ids = []
+ hda_ids.extend(
+ [row.id for row in hda_ids_query.execute()])
+
+ # Now find the tool_id that generated the dataset (even if it was copied)
+ tool_matched_ids = []
+ if tool_id is not None:
+ for hda_id in hda_ids:
+ this_tool_id = _get_tool_id_for_hda(app, hda_id)
+ if this_tool_id is not None and tool_id in this_tool_id:
+ tool_matched_ids.append(hda_id)
+ hda_ids = tool_matched_ids
+
+ deleted_instance_count = 0
+ user_notifications = defaultdict(list)
+
+ # Process each of the Dataset objects
+ for hda_id in hda_ids:
+ user_query = sa.select(
+ [app.model.HistoryDatasetAssociation.table,
+ app.model.History.table,
+ app.model.User.table],
+ whereclause=and_(
+ app.model.HistoryDatasetAssociation.table.c.id == hda_id),
+ from_obj=[sa.join(app.model.User.table,
+ app.model.History.table)
+ .join(app.model.HistoryDatasetAssociation.table)],
+ use_labels=True)
+ for result in user_query.execute():
+ user_notifications[result[app.model.User.table.c.email]].append(
+ (result[app.model.HistoryDatasetAssociation.table.c.name],
+ result[app.model.History.table.c.name]))
+ deleted_instance_count += 1
+ if not info_only and not email_only:
+ # Get the HistoryDatasetAssociation objects
+ hda = app.sa_session.query(
+ app.model.HistoryDatasetAssociation).get(hda_id)
+ if not hda.deleted:
+ # Mark the HistoryDatasetAssociation as deleted
+ hda.deleted = True
+ app.sa_session.add(hda)
+ print ("Marked HistoryDatasetAssociation id %d as "
+ "deleted" % hda.id)
+ app.sa_session.flush()
+
+ emailtemplate = Template(filename=template_file)
+ for (email, dataset_list) in user_notifications.iteritems():
+ msgtext = emailtemplate.render(email=email,
+ datasets=dataset_list,
+ cutoff=cutoff_days)
+ subject = "Galaxy Server Cleanup " \
+ "- %d datasets DELETED" % len(dataset_list)
+ fromaddr = config.error_email_to
+ print ""
+ print "From: %s" % fromaddr
+ print "To: %s" % email
+ print "Subject: %s" % subject
+ print "----------"
+ print msgtext
+ if not info_only:
+ #msg = MIMEText(msgtext)
+ #msg['Subject'] = subject
+ #msg['From'] = 'noone(a)nowhere.com'
+ #msg['To'] = email
+ galaxy.util.send_mail(fromaddr, email, subject,
+ msgtext, config)
+ #s = smtplib.SMTP(smtp_server)
+ #s.sendmail(['lparsons(a)princeton.edu'], email, msg.as_string())
+ #s.quit()
+
+ stop = time.time()
+ print ""
+ print "Marked %d dataset instances as deleted" % deleted_instance_count
+ print "Total elapsed time: ", stop - start
+ print "##########################################"
+
+
+def _get_tool_id_for_hda(app, hda_id):
+ # TODO Some datasets don't seem to have an entry in jtod or a copied_from
+ if hda_id is None:
+ return None
+ job = app.sa_session.query(app.model.Job).\
+ join(app.model.JobToOutputDatasetAssociation).\
+ filter(app.model.JobToOutputDatasetAssociation.table.c.dataset_id ==
+ hda_id).first()
+ if job is not None:
+ return job.tool_id
+ else:
+ hda = app.sa_session.query(app.model.HistoryDatasetAssociation).\
+ get(hda_id)
+ return _get_tool_id_for_hda(app, hda.
+ copied_from_history_dataset_association_id)
+
+
+if __name__ == "__main__":
+ main()
diff -r 69bec229bdf85900f7d581e735aa69ee2cc2aeb9 -r 1e30cdb6d3b82a68da8daddc86411eecc33be444 scripts/cleanup_datasets/admin_cleanup_deletion_template.txt.sample
--- /dev/null
+++ b/scripts/cleanup_datasets/admin_cleanup_deletion_template.txt.sample
@@ -0,0 +1,11 @@
+Galaxy Server Cleanup
+---------------------
+The following datasets you own on Galaxy are older than ${cutoff} days and have been DELETED:
+
+% for dataset, history in datasets:
+ "${dataset}" in history "${history}"
+% endfor
+
+You may be able to undelete them by logging into Galaxy, navigating to the appropriate history, selecting "Include Deleted Datasets" from the history options menu, and clicking on the link to undelete each dataset that you want to keep. You can then download the datasets. Thank you for your understanding and cooporation in this necessary cleanup in order to keep the Galaxy resource available. Please don't hesitate to contact us if you have any questions.
+
+ -- Galaxy Administrators
diff -r 69bec229bdf85900f7d581e735aa69ee2cc2aeb9 -r 1e30cdb6d3b82a68da8daddc86411eecc33be444 scripts/cleanup_datasets/admin_cleanup_warning_template.txt.sample
--- /dev/null
+++ b/scripts/cleanup_datasets/admin_cleanup_warning_template.txt.sample
@@ -0,0 +1,11 @@
+Galaxy Server Cleanup
+---------------------
+The following datasets you own on Galaxy are older than ${cutoff} days and will be deleted soon. Be sure to download any datasets you need to keep.
+
+% for dataset, history in datasets:
+ "${dataset}" in history "${history}"
+% endfor
+
+Please contact us if you have any questions.
+
+ -- Galaxy Administrators
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: Framework enhancements for handling installation of repositories into Galaxy that have repository dependencies that are needed only for compiling a tool dependency.
by commits-noreply@bitbucket.org 10 Sep '13
by commits-noreply@bitbucket.org 10 Sep '13
10 Sep '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/69bec229bdf8/
Changeset: 69bec229bdf8
User: greg
Date: 2013-09-10 17:59:22
Summary: Framework enhancements for handling installation of repositories into Galaxy that have repository dependencies that are needed only for compiling a tool dependency.
Affected #: 7 files
diff -r 82833b9b6f4fbdf1408864bbf7781a02200ca633 -r 69bec229bdf85900f7d581e735aa69ee2cc2aeb9 lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -2280,8 +2280,20 @@
handled_key_rd_dicts=None )
if metadata:
if 'repository_dependencies' in metadata and not repository_dependencies:
- message += 'The repository dependency definitions for this repository are invalid and will be ignored.'
- status = 'error'
+ # See if we have an invalid repository dependency definition or if the repository dependency is required only for compiling the
+ # repository's tool dependency.
+ invalid = False
+ repository_dependencies_dict = metadata[ 'repository_dependencies' ]
+ rd_tups = repository_dependencies_dict.get( 'repository_dependencies', [] )
+ for rd_tup in rd_tups:
+ rdtool_shed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required, rd_only_if_compiling_contained_td = \
+ common_util.parse_repository_dependency_tuple( rd_tup )
+ if not util.asbool( rd_only_if_compiling_contained_td ):
+ invalid = True
+ break
+ if invalid:
+ message += 'The repository dependency definitions for this repository are invalid and will be ignored.'
+ status = 'error'
else:
repository_metadata_id = None
metadata = None
@@ -2718,20 +2730,8 @@
name = kwd.get( 'name', None )
owner = kwd.get( 'owner', None )
changeset_revision = kwd.get( 'changeset_revision', None )
- repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
- repo_dir = repository.repo_path( trans.app )
- repo = hg.repository( suc.get_configured_ui(), repo_dir )
- # Get the upper bound changeset revision.
- upper_bound_changeset_revision = suc.get_next_downloadable_changeset_revision( repository, repo, changeset_revision )
- # Build the list of changeset revision hashes defining each available update up to, but excluding, upper_bound_changeset_revision.
- changeset_hashes = []
- for changeset in suc.reversed_lower_upper_bounded_changelog( repo, changeset_revision, upper_bound_changeset_revision ):
- # Make sure to exclude upper_bound_changeset_revision.
- if changeset != upper_bound_changeset_revision:
- changeset_hashes.append( str( repo.changectx( changeset ) ) )
- if changeset_hashes:
- changeset_hashes_str = ','.join( changeset_hashes )
- return changeset_hashes_str
+ if name and owner and changeset_revision:
+ return suc.get_updated_changeset_revisions( trans, name, owner, changeset_revision )
return ''
@web.expose
diff -r 82833b9b6f4fbdf1408864bbf7781a02200ca633 -r 69bec229bdf85900f7d581e735aa69ee2cc2aeb9 lib/tool_shed/galaxy_install/install_manager.py
--- a/lib/tool_shed/galaxy_install/install_manager.py
+++ b/lib/tool_shed/galaxy_install/install_manager.py
@@ -270,7 +270,8 @@
continue
for rd_tup in rd_tups:
prior_install_ids = []
- tool_shed, name, owner, changeset_revision, prior_installation_required = common_util.parse_repository_dependency_tuple( rd_tup )
+ tool_shed, name, owner, changeset_revision, prior_installation_required, only_if_compiling_contained_td = \
+ common_util.parse_repository_dependency_tuple( rd_tup )
if util.asbool( prior_installation_required ):
for tsr in tool_shed_repositories:
if tsr.name == name and tsr.owner == owner and tsr.changeset_revision == changeset_revision:
diff -r 82833b9b6f4fbdf1408864bbf7781a02200ca633 -r 69bec229bdf85900f7d581e735aa69ee2cc2aeb9 lib/tool_shed/util/common_util.py
--- a/lib/tool_shed/util/common_util.py
+++ b/lib/tool_shed/util/common_util.py
@@ -46,8 +46,8 @@
if rd_key in [ 'root_key', 'description' ]:
continue
for rd_tup in rd_tups:
- tool_shed, name, owner, changeset_revision, prior_installation_required, only_if_compiling_contained_td \
- = parse_repository_dependency_tuple( rd_tup )
+ tool_shed, name, owner, changeset_revision, prior_installation_required, only_if_compiling_contained_td = \
+ parse_repository_dependency_tuple( rd_tup )
tool_shed_accessible, tool_dependencies = get_tool_dependencies( app,
tool_shed,
name,
diff -r 82833b9b6f4fbdf1408864bbf7781a02200ca633 -r 69bec229bdf85900f7d581e735aa69ee2cc2aeb9 lib/tool_shed/util/container_util.py
--- a/lib/tool_shed/util/container_util.py
+++ b/lib/tool_shed/util/container_util.py
@@ -984,7 +984,7 @@
tool_dependency_id=None,
is_orphan='Orphan' )
folder.tool_dependencies.append( tool_dependency )
- is_orphan_description = "these dependencies may not be required by tools in this repository"
+ not_used_by_local_tools_description = "these dependencies may not be required by tools in this repository"
for dependency_key, requirements_dict in tool_dependencies.items():
tool_dependency_id += 1
if dependency_key in [ 'set_environment' ]:
@@ -995,7 +995,7 @@
# TODO: handle this is Galaxy
is_orphan = False
if is_orphan:
- folder.description = is_orphan_description
+ folder.description = not_used_by_local_tools_description
name = set_environment_dict.get( 'name', None )
type = set_environment_dict[ 'type' ]
repository_id = set_environment_dict.get( 'repository_id', None )
@@ -1018,10 +1018,9 @@
if trans.webapp.name == 'tool_shed':
is_orphan = requirements_dict.get( 'is_orphan', False )
else:
- # TODO: handle this is Galaxy
is_orphan = False
if is_orphan:
- folder.description = is_orphan_description
+ folder.description = not_used_by_local_tools_description
name = requirements_dict[ 'name' ]
version = requirements_dict[ 'version' ]
type = requirements_dict[ 'type' ]
diff -r 82833b9b6f4fbdf1408864bbf7781a02200ca633 -r 69bec229bdf85900f7d581e735aa69ee2cc2aeb9 lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -19,7 +19,9 @@
from tool_shed.util import tool_dependency_util
from tool_shed.util import tool_util
from tool_shed.util import xml_util
+from tool_shed.galaxy_install.tool_dependencies import install_util
from tool_shed.galaxy_install.tool_dependencies import td_common_util
+import tool_shed.repository_types.util as rt_util
import pkg_resources
@@ -904,10 +906,18 @@
repository_dependency_tups=invalid_repository_dependency_tups,
is_valid=False,
description=description )
- # Determine and store orphan tool dependencies.
- orphan_tool_dependencies = get_orphan_tool_dependencies( metadata_dict )
- if orphan_tool_dependencies:
- metadata_dict[ 'orphan_tool_dependencies' ] = orphan_tool_dependencies
+ # We need to continue to restrict the behavior of orphan tool dependencies, possibly eliminating them altoghether at some point.
+ check_for_orphan_tool_dependencies = False
+ if app.name == 'tool_shed':
+ if repository.type == rt_util.UNRESTRICTED and 'tools' not in metadata_dict:
+ check_for_orphan_tool_dependencies = True
+ elif 'tools' in metadata_dict:
+ check_for_orphan_tool_dependencies = True
+ if check_for_orphan_tool_dependencies:
+ # Determine and store orphan tool dependencies.
+ orphan_tool_dependencies = get_orphan_tool_dependencies( metadata_dict )
+ if orphan_tool_dependencies:
+ metadata_dict[ 'orphan_tool_dependencies' ] = orphan_tool_dependencies
return metadata_dict, error_message
def generate_tool_metadata( tool_config, tool, repository_clone_url, metadata_dict ):
@@ -1128,16 +1138,6 @@
sample_file_metadata_paths.append( relative_path_to_sample_file )
return sample_file_metadata_paths, sample_file_copy_paths
-def get_updated_changeset_revisions_from_tool_shed( app, tool_shed_url, name, owner, changeset_revision ):
- """
- Get all appropriate newer changeset revisions for the repository defined by the received tool_shed_url / name / owner combination.
- """
- url = suc.url_join( tool_shed_url,
- 'repository/updated_changeset_revisions?name=%s&owner=%s&changeset_revision=%s' %
- ( name, owner, changeset_revision ) )
- text = common_util.tool_shed_get( app, tool_shed_url, url )
- return text
-
def handle_existing_tool_dependencies_that_changed_in_update( app, repository, original_dependency_dict, new_dependency_dict ):
"""
This method is called when a Galaxy admin is getting updates for an installed tool shed repository in order to cover the case where an
@@ -1188,7 +1188,7 @@
return repository_dependency_tup, is_valid, error_message
else:
# Send a request to the tool shed to retrieve appropriate additional changeset revisions with which the repository may have been installed.
- text = get_updated_changeset_revisions_from_tool_shed( app, toolshed, name, owner, changeset_revision )
+ text = install_util.get_updated_changeset_revisions_from_tool_shed( app, toolshed, name, owner, changeset_revision )
if text:
updated_changeset_revisions = util.listify( text )
for updated_changeset_revision in updated_changeset_revisions:
diff -r 82833b9b6f4fbdf1408864bbf7781a02200ca633 -r 69bec229bdf85900f7d581e735aa69ee2cc2aeb9 lib/tool_shed/util/repository_dependency_util.py
--- a/lib/tool_shed/util/repository_dependency_util.py
+++ b/lib/tool_shed/util/repository_dependency_util.py
@@ -1,7 +1,9 @@
import logging
import os
from galaxy import eggs
+from galaxy.util import asbool
from galaxy.util import json
+from galaxy.util import listify
import tool_shed.util.shed_util_common as suc
from tool_shed.util import common_util
from tool_shed.util import common_install_util
@@ -263,9 +265,9 @@
message = '%s ' % str( error )
return message
-def get_key_for_repository_changeset_revision( toolshed_base_url, repository, repository_metadata, all_repository_dependencies ):
+def get_key_for_repository_changeset_revision( trans, toolshed_base_url, repository, repository_metadata, all_repository_dependencies ):
prior_installation_required, only_if_compiling_contained_td = \
- get_prior_installation_required_and_only_if_compiling_contained_td( toolshed_base_url, repository, repository_metadata, all_repository_dependencies )
+ get_prior_installation_required_and_only_if_compiling_contained_td( trans, toolshed_base_url, repository, repository_metadata, all_repository_dependencies )
# Create a key with the value of prior_installation_required defaulted to False.
key = container_util.generate_repository_dependencies_key_for_repository( toolshed_base_url=toolshed_base_url,
repository_name=repository.name,
@@ -275,21 +277,47 @@
only_if_compiling_contained_td=only_if_compiling_contained_td )
return key
-def get_prior_installation_required_and_only_if_compiling_contained_td( toolshed_base_url, repository, repository_metadata, all_repository_dependencies ):
+def get_prior_installation_required_and_only_if_compiling_contained_td( trans, toolshed_base_url, repository, repository_metadata, all_repository_dependencies ):
"""
- If all_repository_dependencies contains a repository dependency tuple that is associated with the received repository, return the
- value of the tuple's prior_installation_required component.
+ This method is called from the tool shed and never Galaxy. If all_repository_dependencies contains a repository dependency tuple that is associated with
+ the received repository, return the value of the tuple's prior_installation_required component.
"""
- for rd_key, rd_tups in all_repository_dependencies.items():
- if rd_key in [ 'root_key', 'description' ]:
- continue
+ if all_repository_dependencies:
+ for rd_key, rd_tups in all_repository_dependencies.items():
+ if rd_key in [ 'root_key', 'description' ]:
+ continue
+ for rd_tup in rd_tups:
+ rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required, rd_only_if_compiling_contained_td = \
+ common_util.parse_repository_dependency_tuple( rd_tup )
+ if rd_toolshed == toolshed_base_url and \
+ rd_name == repository.name and \
+ rd_owner == repository.user.username and \
+ rd_changeset_revision == repository_metadata.changeset_revision:
+ return rd_prior_installation_required, rd_only_if_compiling_contained_td
+ elif repository_metadata:
+ # Get the list of changeset revisions from the tool shed to which the repository may be updated.
+ metadata = repository_metadata.metadata
+ current_changeset_revision = str( repository_metadata.changeset_revision )
+ # Get the changeset revision to which the current value of required_repository_changeset_revision should be updated if it's not current.
+ text = suc.get_updated_changeset_revisions( trans,
+ name=str( repository.name ),
+ owner=str( repository.user.username ),
+ changeset_revision=current_changeset_revision )
+ if text:
+ valid_changeset_revisions = listify( text )
+ if current_changeset_revision not in valid_changeset_revisions:
+ valid_changeset_revisions.append( current_changeset_revision )
+ else:
+ valid_changeset_revisions = [ current_changeset_revision ]
+ repository_dependencies_dict = metadata[ 'repository_dependencies' ]
+ rd_tups = repository_dependencies_dict.get( 'repository_dependencies', [] )
for rd_tup in rd_tups:
rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required, rd_only_if_compiling_contained_td = \
common_util.parse_repository_dependency_tuple( rd_tup )
if rd_toolshed == toolshed_base_url and \
rd_name == repository.name and \
rd_owner == repository.user.username and \
- rd_changeset_revision == repository_metadata.changeset_revision:
+ rd_changeset_revision in valid_changeset_revisions:
return rd_prior_installation_required, rd_only_if_compiling_contained_td
# Default both prior_installation_required and only_if_compiling_contained_td to False.
return 'False', 'False'
@@ -333,7 +361,11 @@
metadata = repository_metadata.metadata
if metadata:
if 'repository_dependencies' in metadata:
- current_repository_key = get_key_for_repository_changeset_revision( toolshed_base_url, repository, repository_metadata, all_repository_dependencies )
+ current_repository_key = get_key_for_repository_changeset_revision( trans,
+ toolshed_base_url,
+ repository,
+ repository_metadata,
+ all_repository_dependencies )
repository_dependencies_dict = metadata[ 'repository_dependencies' ]
if not all_repository_dependencies:
all_repository_dependencies = initialize_all_repository_dependencies( current_repository_key,
@@ -583,6 +615,22 @@
return True
return False
+def filter_only_if_compiling_contained_td( key_rd_dict ):
+ """
+ Return a copy of the received key_rd_dict with repository dependencies that are needed only_if_compiling_contained_td filtered out
+ of the list of repository dependencies for each rd_key.
+ """
+ filtered_key_rd_dict = {}
+ for rd_key, required_rd_tup in key_rd_dict.items():
+ tool_shed, name, owner, changeset_revision, prior_installation_required, only_if_compiling_contained_td = \
+ common_util.parse_repository_dependency_tuple( required_rd_tup )
+ if not asbool( only_if_compiling_contained_td ):
+ if rd_key in filtered_key_rd_dict:
+ filtered_key_rd_dict[ rd_key ].append( required_rd_tup )
+ else:
+ filtered_key_rd_dict[ rd_key ] = [ required_rd_tup ]
+ return filtered_key_rd_dict
+
def merge_missing_repository_dependencies_to_installed_container( containers_dict ):
"""Merge the list of missing repository dependencies into the list of installed repository dependencies."""
missing_rd_container_root = containers_dict.get( 'missing_repository_dependencies', None )
@@ -629,32 +677,35 @@
current_repository_key_rd_dicts = remove_ropository_dependency_reference_to_self( current_repository_key_rd_dicts )
current_repository_key_rd_dicts = get_updated_changeset_revisions_for_repository_dependencies( trans, current_repository_key_rd_dicts )
for key_rd_dict in current_repository_key_rd_dicts:
- is_circular = False
- if not in_key_rd_dicts( key_rd_dict, handled_key_rd_dicts ) and not in_key_rd_dicts( key_rd_dict, key_rd_dicts_to_be_processed ):
- filtered_current_repository_key_rd_dicts.append( key_rd_dict )
- repository_dependency = key_rd_dict[ current_repository_key ]
- if current_repository_key in all_repository_dependencies:
- # Add all repository dependencies for the current repository into it's entry in all_repository_dependencies.
- all_repository_dependencies_val = all_repository_dependencies[ current_repository_key ]
- if repository_dependency not in all_repository_dependencies_val:
- all_repository_dependencies_val.append( repository_dependency )
- all_repository_dependencies[ current_repository_key ] = all_repository_dependencies_val
- elif not in_all_repository_dependencies( current_repository_key, repository_dependency, all_repository_dependencies ):
- # Handle circular repository dependencies.
- if is_circular_repository_dependency( current_repository_key, repository_dependency, all_repository_dependencies ):
- is_circular = True
- circular_repository_dependencies, handled_key_rd_dicts, all_repository_dependencies = \
- handle_circular_repository_dependency( current_repository_key,
- repository_dependency,
- circular_repository_dependencies,
- handled_key_rd_dicts,
- all_repository_dependencies )
- else:
- all_repository_dependencies[ current_repository_key ] = [ repository_dependency ]
- if not is_circular and can_add_to_key_rd_dicts( key_rd_dict, key_rd_dicts_to_be_processed ):
- new_key_rd_dict = {}
- new_key_rd_dict[ current_repository_key ] = repository_dependency
- key_rd_dicts_to_be_processed.append( new_key_rd_dict )
+ # Filter out repository dependencies that are required only if compiling the dependent repository's tool dependency.
+ all_repository_dependencieskey_rd_dict = filter_only_if_compiling_contained_td( key_rd_dict )
+ if key_rd_dict:
+ is_circular = False
+ if not in_key_rd_dicts( key_rd_dict, handled_key_rd_dicts ) and not in_key_rd_dicts( key_rd_dict, key_rd_dicts_to_be_processed ):
+ filtered_current_repository_key_rd_dicts.append( key_rd_dict )
+ repository_dependency = key_rd_dict[ current_repository_key ]
+ if current_repository_key in all_repository_dependencies:
+ # Add all repository dependencies for the current repository into it's entry in all_repository_dependencies.
+ all_repository_dependencies_val = all_repository_dependencies[ current_repository_key ]
+ if repository_dependency not in all_repository_dependencies_val:
+ all_repository_dependencies_val.append( repository_dependency )
+ all_repository_dependencies[ current_repository_key ] = all_repository_dependencies_val
+ elif not in_all_repository_dependencies( current_repository_key, repository_dependency, all_repository_dependencies ):
+ # Handle circular repository dependencies.
+ if is_circular_repository_dependency( current_repository_key, repository_dependency, all_repository_dependencies ):
+ is_circular = True
+ circular_repository_dependencies, handled_key_rd_dicts, all_repository_dependencies = \
+ handle_circular_repository_dependency( current_repository_key,
+ repository_dependency,
+ circular_repository_dependencies,
+ handled_key_rd_dicts,
+ all_repository_dependencies )
+ else:
+ all_repository_dependencies[ current_repository_key ] = [ repository_dependency ]
+ if not is_circular and can_add_to_key_rd_dicts( key_rd_dict, key_rd_dicts_to_be_processed ):
+ new_key_rd_dict = {}
+ new_key_rd_dict[ current_repository_key ] = repository_dependency
+ key_rd_dicts_to_be_processed.append( new_key_rd_dict )
return filtered_current_repository_key_rd_dicts, key_rd_dicts_to_be_processed, handled_key_rd_dicts, all_repository_dependencies
def prune_invalid_repository_dependencies( repository_dependencies ):
diff -r 82833b9b6f4fbdf1408864bbf7781a02200ca633 -r 69bec229bdf85900f7d581e735aa69ee2cc2aeb9 lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -1190,6 +1190,27 @@
return {}
return tool_shed_status_dict
+def get_updated_changeset_revisions( trans, name, owner, changeset_revision ):
+ """
+ Return a string of comma-separated changeset revision hashes for all available updates to the received changeset revision for the repository
+ defined by the received name and owner.
+ """
+ repository = get_repository_by_name_and_owner( trans.app, name, owner )
+ repo_dir = repository.repo_path( trans.app )
+ repo = hg.repository( get_configured_ui(), repo_dir )
+ # Get the upper bound changeset revision.
+ upper_bound_changeset_revision = get_next_downloadable_changeset_revision( repository, repo, changeset_revision )
+ # Build the list of changeset revision hashes defining each available update up to, but excluding, upper_bound_changeset_revision.
+ changeset_hashes = []
+ for changeset in reversed_lower_upper_bounded_changelog( repo, changeset_revision, upper_bound_changeset_revision ):
+ # Make sure to exclude upper_bound_changeset_revision.
+ if changeset != upper_bound_changeset_revision:
+ changeset_hashes.append( str( repo.changectx( changeset ) ) )
+ if changeset_hashes:
+ changeset_hashes_str = ','.join( changeset_hashes )
+ return changeset_hashes_str
+ return ''
+
def get_url_from_tool_shed( app, tool_shed ):
"""
The value of tool_shed is something like: toolshed.g2.bx.psu.edu. We need the URL to this tool shed, which is something like:
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