diff --git a/README b/README index 72193b94e370cb6ff29d53ab22d43a6e7eb217fb..3f019a0c0699cc90171f9dc3030307146fd932de 100644 --- a/README +++ b/README @@ -57,6 +57,7 @@ Todo: * Create a web interface url to watch the progress of a batch job. * Use virtualenv? * Perhaps the WSGI file should be somewhere else and be called mutalyzer.wsgi? +* Password for MySQL user. Notes for server setup (Europium VM copy): diff --git a/bin/mutalyzer-batchd b/bin/mutalyzer-batchd index c7bd01759acf86c1e03d674ef74765cc215361b8..d02c323829b033d3a72844b80a16e18ce3f13699 100755 --- a/bin/mutalyzer-batchd +++ b/bin/mutalyzer-batchd @@ -8,6 +8,7 @@ should be run with the mutalyzer directory as working directory. @todo: Check if PID dir is writable. @todo: Get rid of ugly exception logging. +@todo: Reload configuration without restarting (for example, on SIGHUP). [1] http://pypi.python.org/pypi/python-daemon/ """ diff --git a/extras/apache/mutalyzer.conf b/extras/apache/mutalyzer.conf new file mode 100644 index 0000000000000000000000000000000000000000..fdd3382000e1c90057bc3b81cf6ff6e7ef4a15f0 --- /dev/null +++ b/extras/apache/mutalyzer.conf @@ -0,0 +1,10 @@ +Alias /mutalyzer/base <MUTALYZER_PACKAGE_ROOT>/templates/base + +WSGIScriptAlias /mutalyzer/services <MUTALYZER_PACKAGE_ROOT>/webservice.py +WSGIScriptAlias /mutalyzer <MUTALYZER_PACKAGE_ROOT>/wsgi.py + +<Directory <MUTALYZER_PACKAGE_ROOT>/> + Order deny,allow + Allow from all + AllowOverride None +</Directory> diff --git a/extras/init.d/mutalyzer-batchd b/extras/init.d/mutalyzer-batchd old mode 100755 new mode 100644 index 9c559f2427f89b7c2dadff17468eaaf6c3002b28..c94763440847e1172d77c14247a0ea694dd85817 --- a/extras/init.d/mutalyzer-batchd +++ b/extras/init.d/mutalyzer-batchd @@ -1,6 +1,6 @@ #! /bin/sh ### BEGIN INIT INFO -# Provides: mutalyzer-batch-daemon +# Provides: mutalyzer-batchd # Required-Start: $local_fs $remote_fs $network $syslog $mysql # Required-Stop: $local_fs $remote_fs $network $syslog $mysql # Default-Start: 2 3 4 5 @@ -9,26 +9,21 @@ # Description: Controls the Mutalyzer batch job processing daemon.. ### END INIT INFO -# Author: Martijn Vermaat <m.vermaat.hg@lumc.nl> - -# Do NOT "set -e" - -# PATH should only include /usr/* if it runs after the mountnfs.sh script PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="Mutalyzer batch deamon" -DAEMON=/home/martijn/projects/mutalyzer/svn/branches/refactor-mutalyzer-branch/bin/mutalyzer-batchd -DIR=/home/martijn/projects/mutalyzer/svn/branches/refactor-mutalyzer-branch NAME=mutalyzer-batchd -PIDFILE=/var/run/mutalyzer/mutalyzer-batchd.pid +DAEMON=<MUTALYZER_BIN_BATCHD> +DIR=<MUTALYZER_PACKAGE_ROOT> PIDDIR=/var/run/mutalyzer -SCRIPTNAME=/etc/init.d/mutalyzer-batchd +PIDFILE=$PIDDIR/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME USER=www-data # Exit if the package is not installed [ -x "$DAEMON" ] || exit 0 # Read configuration variable file if it is present -[ -r /etc/default/mutalyzer ] && . /etc/default/mutalyzer +[ -r /etc/default/$NAME ] && . /etc/default/$NAME # Load the VERBOSE setting and other rcS variables . /lib/init/vars.sh diff --git a/extras/post-install.sh b/extras/post-install.sh index 35ff4468f0f4cd0356409dd132d46e74845d8fdb..1f96e26eaf923f73150645adc9d71d08960b0533 100644 --- a/extras/post-install.sh +++ b/extras/post-install.sh @@ -8,9 +8,17 @@ # Todo: # - Database setup +# - Apache setup # - Copy doc to /usr/share/doc -if [ ! -f /etc/mutalyzer/config ]; do +set -e + +# The 'cd /' is a hack to prevent the mutalyzer package under the current +# directory to be used. +PACKAGE_ROOT=$(cd / && python -c 'import mutalyzer; print mutalyzer.package_root()') +BIN_BATCHD=$(which mutalyzer-batchd) + +if [ ! -e /etc/mutalyzer/config ]; then mkdir -p /etc/mutalyzer cp extras/config.example /etc/mutalyzer/config chmod -R u=rwX,go=rX /etc/mutalyzer @@ -24,7 +32,14 @@ mkdir -p /var/cache/mutalyzer chown -R www-data:www-data /var/cache/mutalyzer chmod -R u=rwX,go=rX /var/cache/mutalyzer -if [ ! -f /etc/init.d/mutalyzer-batchd ]; do +if [ ! -e /etc/init.d/mutalyzer-batchd ]; then cp extras/init.d/mutalyzer-batchd /etc/init.d/mutalyzer-batchd + sed -i -e "s@<MUTALYZER_PACKAGE_ROOT>@${PACKAGE_ROOT}@g" -e "s@<MUTALYZER_BIN_BATCHD>@${BIN_BATCHD}@g" /etc/init.d/mutalyzer-batchd chmod u=rwx,go=rx /etc/init.d/mutalyzer-batchd fi + +if [ ! -e /etc/apache2/conf.d/mutalyzer.conf ]; then + cp extras/apache/mutalyzer.conf /etc/apache2/conf.d/mutalyzer.conf + sed -i -e "s@<MUTALYZER_PACKAGE_ROOT>@${PACKAGE_ROOT}@g" -e "s@<MUTALYZER_BIN_BATCHD>@${BIN_BATCHD}@g" /etc/apache2/conf.d/mutalyzer.conf + chmod u=rw,go=r /etc/apache2/conf.d/mutalyzer.conf +fi diff --git a/mutalyzer/__init__.py b/mutalyzer/__init__.py index 693f197560ee2f2d32fddf0d7fb371be0138e2d9..20be9eafb9d58e0c583d4b3edfb88acc09a260be 100644 --- a/mutalyzer/__init__.py +++ b/mutalyzer/__init__.py @@ -1,6 +1,9 @@ """HGVS variant nomenclature checker.""" +import os + + # On the event of a new release, we update the __version_info__ and __date__ # package globals and set RELEASE to True. # After a release, a development version is denoted by a __version_info__ @@ -21,3 +24,7 @@ __homepage__ = 'http://mutalyzer.nl' NOMENCLATURE_VERSION_INFO = ('2', '0') NOMENCLATURE_VERSION = '.'.join(NOMENCLATURE_VERSION_INFO) + + +def package_root(): + return os.path.split(__file__)[0] diff --git a/mutalyzer/wsgi.py b/mutalyzer/wsgi.py index 311dd6e76d36d2cf7a1f26ab7eca2ce05c0909e1..4bd4f47e9ded55c84db8412644b276163599a29e 100644 --- a/mutalyzer/wsgi.py +++ b/mutalyzer/wsgi.py @@ -85,6 +85,7 @@ config = Config() # URL dispatch table urls = ( + '', 'RedirectHome', '/(index)?', 'Static', '/(about)', 'Static', '/(help)', 'Static', @@ -204,6 +205,23 @@ render = render_tal('templates', globals={ app = web.application(urls, globals(), autoreload=False) +class RedirectHome: + """ + Permanent redirect to the homepage. + """ + def GET(self): + """ + Redirect to / and include the query string. + """ + raise web.redirect('/' + web.ctx.query) + + def POST(self): + """ + Redirect to / and include the query string. + """ + raise web.redirect('/' + web.ctx.query) + + class Download: """ Download file from template directory, formatting it first. @@ -1107,5 +1125,6 @@ if __name__ == '__main__': else: # WSGI application # Todo: Fix Mutalyzer to not depend on working directory - os.chdir(os.path.dirname(__file__)) + #os.chdir(os.path.dirname(__file__)) + os.chdir(mutalyzer.package_root()) application = app.wsgifunc() diff --git a/setup.py b/setup.py index 64219d5b7403d7fa009e76ee04beb600ee506286..33e002f72b06b7d73e4818c6758af4ea37cc0870 100644 --- a/setup.py +++ b/setup.py @@ -27,4 +27,4 @@ setup( # - Chown /var/log/mutalyzer.log and /var/cache/mutalyzer # - Copy extras/init.d/mutalyzer-batchd to /etc/init.d/mutalyzer-batchd # - Copy doc to /usr/share/doc -# Perhaps as a postinstall script? +# Check extras/post-install.sh for these. diff --git a/tests/config b/tests/config new file mode 100644 index 0000000000000000000000000000000000000000..4fb75eab7966b6f9fbc576da69f2211a7df88de3 --- /dev/null +++ b/tests/config @@ -0,0 +1,157 @@ +# +# Mutalyzer config file. +# +# Copy this file to /etc/mutalyzer/config or ~/.config/mutalyzer/config and +# modify to suit your preferences. + +# +# These settings are used by the Retriever module. +# + +# Use this email address for retrieval of records at the NCBI. +email = "m.vermaat.hg@lumc.nl" + +# The cache directory. +cache = "/var/cache/mutalyzer" + +# The maximum size of the cache in megabytes. +cachesize = 50 + +# The maximum size of a downloaded GenBank file in megabytes. +maxDldSize = 10 + +# The minimum size of a downloaded GenBank file in bytes. +minDldSize = 512 + +# The URL from where LRG files are fetched +lrgurl = "ftp://ftp.ebi.ac.uk/pub/databases/lrgex/" + + +# +# These settings are used by the Db module. +# + +# Internal database. +internalDb = "mutalyzer" + +# MySQL mapping database names. +dbNames = "hg18", "hg19" + +# MySQL username for the local databases (internalDb and dbNames). +LocalMySQLuser = "mutalyzer" + +# Host name for the local databases. +LocalMySQLhost = "localhost" + +# MySQL username for the UCSC database. +RemoteMySQLuser = "genome" + +# Host name for the UCSC database. +RemoteMySQLhost = "genome-mysql.cse.ucsc.edu" + +# Retrieve all entries modified within a certain number of days. +UpdateInterval = 7 + + +# +# These settings are used by the Output module. +# + +# Name and location of the log file. +log = "/tmp/mutalyzer-tests.log" + +# Prefix for each log message. +datestring = "%Y-%m-%d %H:%M:%S" + +# Message levels: +# +# 0 : Debug ; Show all messages. +# 1 : Info ; Show all messages except debug messages. +# 2 : Warning ; Show warning, error and fatal messages. +# 3 : Error ; Show error and fatal messages. +# 4 : Fatal ; Only show fatal messages. +# 5 : Off ; Show nothing. + +# Level of logged messages. +loglevel = 3 + +# Level of output messages. +outputlevel = 1 + + +# +# These settings are used by the Mutator module. +# + +# Length of the flanking sequences (used in the visualisation of mutations). +flanksize = 25 + +# Maximum length of visualised mutations. +maxvissize = 25 + +# Length of the flanking sequences of the clipped mutations (see maxvissize). +flankclipsize = 6 + + +# +# These settings are used by the Scheduler module. +# + +# Name of the batch process. +processName = "MutalyzerBatch2" + +# Return e-mail address. +mailFrom = "noreply@humgen.nl" + +# Subject of the message. +mailSubject = "Result of Mutalyzer batch check." + +# Location of the results. +resultsDir = "/var/cache/mutalyzer" + +# Location of the PID file. +PIDfile = "/var/run/mutalyzer/mutalyzer-batchd.pid" + +# Maximum size for uploaded batch input files in megabytes. +batchInputMaxSize = 5 + +# The output header for NameChecking +nameCheckOutHeader = "Input", "Errors | Messages", "AccNo", "Genesymbol", "Variant", "Reference Sequence Start Descr.", "Coding DNA Descr.", "Protein Descr.", "GeneSymbol Coding DNA Descr.", "GeneSymbol Protein Descr.", "Genomic Reference", "Coding Reference", "Protein Reference", "Affected Transcripts", "Affected Proteins" + +# The output header for SyntaxChecking +syntaxCheckOutHeader = "Input", "Status" + +# The output header for PositionConverter +positionConverterOutHeader = "Input Variant", "Errors", "Chromosomal Variant", "Coding Variant(s)" + +# The output header for SnpConverter +snpConverterOutHeader = "Input Variant", "HGVS description(s)", "Errors | Messages" + + +# +# These settings are used by the File module. +# + +# Amount of bytes to be read for determining the file type. +bufSize = 32768 + +# The obligatory header in batch request files. +header = "AccNo", "Genesymbol", "Mutation" + +# Threshold for Batch Jobs +threshold = 0.05 + + +# +# These settings are used by the GenRecord module. +# + +# Number of upstream nucleotides when searching for a transcript. +upstream = 5000 + +# Number of downstream nucleotides when searching for a transcript. +downstream = 2000 + +spliceAlarm = 2 + +spliceWarn = 5 diff --git a/tests/test_grammar.py b/tests/test_grammar.py index 85ab8276a695d6904938742c3066e8a47408026c..c5564a80ccfa152ff6c559b5d4be68de1aeaef46 100644 --- a/tests/test_grammar.py +++ b/tests/test_grammar.py @@ -7,14 +7,17 @@ Tests for the mutalyzer.grammar module. import os from nose.tools import * +import mutalyzer from mutalyzer.config import Config from mutalyzer.grammar import Grammar from mutalyzer.output import Output +# If we remove the os.chdir below, this is no longer necessary +CONFIG = os.path.realpath('config') + # Todo: Fix Mutalyzer to not depend on working directory -root_dir = os.path.split(os.path.dirname(__file__))[0] -os.chdir(os.path.join(root_dir, 'mutalyzer')) +os.chdir(mutalyzer.package_root()) class TestGrammar(): @@ -26,7 +29,7 @@ class TestGrammar(): """ Initialize test Grammar instance. """ - self.config = Config() + self.config = Config(CONFIG) self.output = Output(__file__, self.config.Output) self.grammar = Grammar(self.output) diff --git a/tests/test_mutalyzer.py b/tests/test_mutalyzer.py index 5304bb170237a467b4cc24af7b9f4d6877d0037d..52ecf1240f533fd5057ece8e57de26cd106577f0 100644 --- a/tests/test_mutalyzer.py +++ b/tests/test_mutalyzer.py @@ -10,14 +10,17 @@ import random from nose.tools import * from Bio.Seq import Seq +import mutalyzer from mutalyzer.config import Config from mutalyzer.output import Output from mutalyzer.variantchecker import check_variant +# If we remove the os.chdir below, this is no longer necessary +CONFIG = os.path.realpath('config') + # Todo: Fix Mutalyzer to not depend on working directory -root_dir = os.path.split(os.path.dirname(__file__))[0] -os.chdir(os.path.join(root_dir, 'mutalyzer')) +os.chdir(mutalyzer.package_root()) class TestMutalyzer(): @@ -29,7 +32,7 @@ class TestMutalyzer(): """ Initialize test Mutalyzer module. """ - self.config = Config() + self.config = Config(CONFIG) self.output = Output(__file__, self.config.Output) def test_roll(self): diff --git a/tests/test_mutator.py b/tests/test_mutator.py index 766270d44703de14984d2877cf056cf935b17e58..b0bf933f5098597d4760a5af8ede0b493715a926 100644 --- a/tests/test_mutator.py +++ b/tests/test_mutator.py @@ -10,14 +10,17 @@ import random from nose.tools import * from Bio.Seq import Seq +import mutalyzer from mutalyzer.config import Config from mutalyzer.output import Output from mutalyzer import mutator +# If we remove the os.chdir below, this is no longer necessary +CONFIG = os.path.realpath('config') + # Todo: Fix Mutalyzer to not depend on working directory -root_dir = os.path.split(os.path.dirname(__file__))[0] -os.chdir(os.path.join(root_dir, 'mutalyzer')) +os.chdir(mutalyzer.package_root()) def _seq(length): @@ -39,7 +42,7 @@ class TestMutator(): """ Initialize test mutator module. """ - self.config = Config() + self.config = Config(CONFIG) self.output = Output(__file__, self.config.Output) def _mutator(self, sequence): @@ -178,7 +181,7 @@ class TestMutator(): sites = [4, 9, 14, 17, 25, 27] m = self._mutator(_seq(l)) m.delM(17, 17) # g.17del - assert_equal(m.newSplice(sites), [4, 9, 14, 16, 24, 27]) + assert_equal(m.newSplice(sites), [4, 9, 14, 16, 24, 26]) def test_newSplice_don_del_after(self): """ diff --git a/tests/test_webservice.py b/tests/test_webservice.py index 2b264f21900651a9c1eb5c3de2b2869be380f16d..df94d12376001a46248f3daed17560b074a13277 100644 --- a/tests/test_webservice.py +++ b/tests/test_webservice.py @@ -10,7 +10,7 @@ from suds import WebFault from nose.tools import * -WSDL_URL = 'http://mutalyzer-refactor.martijn/services/?wsdl' +WSDL_URL = 'http://localhost/mutalyzer/services/?wsdl' class TestWSDL(): diff --git a/tests/test_wsgi.py b/tests/test_wsgi.py index fc8d49643d21f89feec6783ab5030c28c703f46d..f5e399207bd4d792f44eb91c7a2835e7b65e57e1 100644 --- a/tests/test_wsgi.py +++ b/tests/test_wsgi.py @@ -18,12 +18,12 @@ import time from nose.tools import * from webtest import TestApp +import mutalyzer from mutalyzer.wsgi import application # Todo: Fix Mutalyzer to not depend on working directory -root_dir = os.path.split(os.path.dirname(__file__))[0] -os.chdir(os.path.join(root_dir, 'mutalyzer')) +os.chdir(mutalyzer.package_root()) class TestWSGI():