diff --git a/bin/mutalyzer b/bin/mutalyzer index 68345947cd5c43c2f108c842ea6b7d96d32a2800..9013cd39154aeefdad383baa1278ae185cd2d8af 100755 --- a/bin/mutalyzer +++ b/bin/mutalyzer @@ -17,7 +17,6 @@ import os from mutalyzer import variantchecker from mutalyzer.output import Output -from mutalyzer.config import Config from mutalyzer.util import format_usage @@ -27,12 +26,11 @@ def main(cmd): @todo: documentation """ - C = Config() - O = Output(__file__, C.Output) + O = Output(__file__) O.addMessage(__file__, -1, "INFO", "Received variant " + cmd) - RD = variantchecker.check_variant(cmd, C, O) + RD = variantchecker.check_variant(cmd, O) O.addMessage(__file__, -1, "INFO", "Finished processing variant " + cmd) diff --git a/bin/mutalyzer-batchd b/bin/mutalyzer-batchd index 868eafa933fe36a3e7681c2d9641c6d7840fb0f5..2753d8a0032f2528e6c32d80e82e7bcbf93c75cb 100755 --- a/bin/mutalyzer-batchd +++ b/bin/mutalyzer-batchd @@ -23,7 +23,7 @@ import signal import time import traceback -from mutalyzer.config import Config +from mutalyzer import config from mutalyzer.Db import Batch from mutalyzer.Scheduler import Scheduler @@ -40,10 +40,7 @@ def daemonize(): Write PID file when it is not locked and daemonize a loop processing scheduled batch jobs. """ - config = Config() - batch_config = config.Batch - - pidfile = os.path.realpath(batch_config.PIDfile) + pidfile = os.path.realpath(config.get('PIDfile')) lockfile = pidlockfile.TimeoutPIDLockFile(pidfile, acquire_timeout=1, threaded=False) @@ -68,10 +65,10 @@ def daemonize(): with context: # Note that any opened files are now closed. This is not a problem for - # the Config instance, since it does not read its file again after + # the config module, since it does not read its file again after # initialisation. - database = Batch(config.Db) - scheduler = Scheduler(config.Scheduler, database) + database = Batch() + scheduler = Scheduler(database) def stop_scheduler(signum, stack_frame): scheduler.stop() diff --git a/bin/mutalyzer-cache-sync b/bin/mutalyzer-cache-sync index 405084ea16b373b3e0e161a1cc35cb03cb55432b..5e012949ddff2661c4a9a61a42a0639af8e60a58 100755 --- a/bin/mutalyzer-cache-sync +++ b/bin/mutalyzer-cache-sync @@ -20,7 +20,6 @@ This program is intended to be run daily from cron. Example: import sys -from mutalyzer.config import Config from mutalyzer.output import Output from mutalyzer.sync import CacheSync from mutalyzer import Db @@ -31,11 +30,10 @@ def cache_sync(remote_wsdl, url_template, days): """ Synchronize the database cache with other Mutalyzer instances. """ - config = Config() - output = Output(__file__, config.Output) - database = Db.Cache(config.Db) + output = Output(__file__) + database = Db.Cache() - sync = CacheSync(config.Retriever, output, database) + sync = CacheSync(output, database) sync.sync_with_remote(remote_wsdl, url_template, days) diff --git a/bin/mutalyzer-mapping-update b/bin/mutalyzer-mapping-update index cbc88ef27dab3c6f81854a91424605748df7e1dd..8fe6bb3500b289fbe0d69434eabe2e6b85c6e6d5 100755 --- a/bin/mutalyzer-mapping-update +++ b/bin/mutalyzer-mapping-update @@ -19,7 +19,6 @@ This program is intended to be run daily from cron. Example: import sys -from mutalyzer.config import Config from mutalyzer.output import Output from mutalyzer.mapping import NCBIUpdater from mutalyzer.util import format_usage @@ -39,12 +38,11 @@ def main(database, mapping_file, assembly): @todo: Also report how much was added/updated. """ - config = Config() - output = Output(__file__, config.Output) + output = Output(__file__) output.addMessage(__file__, -1, 'INFO', 'Starting NCBI mapping data update') - updater = NCBIUpdater(database, config) + updater = NCBIUpdater(database) updater.load(mapping_file, assembly) updater.merge() diff --git a/bin/mutalyzer-webservice.wsgi b/bin/mutalyzer-webservice.wsgi index bc624da31f7e733ff61b899860ca67f6c2fafb2b..5a01545e2e705cf9b04bc26b14da521c24e8c3d9 100755 --- a/bin/mutalyzer-webservice.wsgi +++ b/bin/mutalyzer-webservice.wsgi @@ -25,8 +25,6 @@ To start the built-in HTTP server on port 8081: kind of strictness checks on the input. For example, in transcriptInfo, the build argument must really be present. (Hint: use __checkBuild.) -@todo: The mutalyzer.config.Config object can just be instantiated once - and we should not create it on every request. """ diff --git a/extras/log-tools/find-crashes.py b/extras/log-tools/find-crashes.py index cea38c2e667cb8ebf0fa3abd5fcf69845b6923d7..0e6d791ef19995d3708a982573b40861822ca71f 100755 --- a/extras/log-tools/find-crashes.py +++ b/extras/log-tools/find-crashes.py @@ -10,11 +10,10 @@ crashed. import os -from mutalyzer.config import Config +from mutalyzer import config -config = Config() -handle = open(config.Output.log, 'r') +handle = open(config.get('log'), 'r') scanning = False line = handle.readline() diff --git a/mutalyzer/Db.py b/mutalyzer/Db.py index 5bd25f3396680cd42ad2eeeb19f42ed23706bffe..60d61a183b9bbdf71fa7d718b3924be9c6e9fd94 100644 --- a/mutalyzer/Db.py +++ b/mutalyzer/Db.py @@ -25,6 +25,7 @@ import warnings import MySQLdb from mutalyzer import util +from mutalyzer import config # @@ -115,7 +116,7 @@ class Mapping(Db) : Database functions for mapping of transcripts and genes. Special methods: - - __init__(build, config) ; Initialise the class. + - __init__(build) ; Initialise the class. Public methods: - get_protAcc(mrnaAcc) ; Query the database for a protein ID. @@ -135,18 +136,15 @@ class Mapping(Db) : - Mapping; Accumulated mapping info. """ - def __init__(self, build, config) : + def __init__(self, build) : """ Initialise the Db parent class. Use the local database for a certain build. @arg build: The version of the mapping database @type build: string - @arg config: Configuration variables - @type config: class instance """ - - Db.__init__(self, build, config.LocalMySQLuser, config.LocalMySQLhost) + Db.__init__(self, build, config.get('LocalMySQLuser'), config.get('LocalMySQLhost')) #__init__ def get_NM_version(self, mrnaAcc) : @@ -660,7 +658,7 @@ class Cache(Db) : Database functions for cache administration. Special methods: - - __init__(config) ; Initialise the class. + - __init__() ; Initialise the class. Public methods: - insertGB(accNo, GI, fileHash, ChrAccVer, ChrStart, ChrStop, @@ -683,16 +681,12 @@ class Cache(Db) : - GBInfo ; Information about cached and uploaded GenBank files. """ - def __init__(self, config) : + def __init__(self) : """ Initialise the Db parent class. Use the internalDb. - - @arg config: Configuration variables - @type config: class instance """ - - Db.__init__(self, config.internalDb, config.LocalMySQLuser, - config.LocalMySQLhost) + Db.__init__(self, config.get('internalDb'), + config.get('LocalMySQLuser'), config.get('LocalMySQLhost')) #__init__ def insertGB(self, accNo, GI, fileHash, ChrAccVer, ChrStart, @@ -1099,7 +1093,7 @@ class Batch(Db) : Database functions for the batch checker. Special methods: - - __init__(config) ; Initialise the class. + - __init__() ; Initialise the class. Public methods: - isJobListEmpty() ; See if there are active jobs. @@ -1121,16 +1115,13 @@ class Batch(Db) : - BatchQueue ; Requests. """ - def __init__(self, config) : + def __init__(self) : """ Initialise the Db parent class. Use the internalDb. - - @arg config: Configuration variables - @type config: class instance """ - - Db.__init__(self, config.internalDb, config.LocalMySQLuser, - config.LocalMySQLhost) + Db.__init__(self, config.get('internalDb'), + config.get('LocalMySQLuser'), + config.get('LocalMySQLhost')) #__init__ def isJobListEmpty(self) : diff --git a/mutalyzer/File.py b/mutalyzer/File.py index a03a1b3af460e35b51057b900348edb8f70a0279..561503d7bd605b968f1af779067bc7c4ea4427e5 100644 --- a/mutalyzer/File.py +++ b/mutalyzer/File.py @@ -27,13 +27,14 @@ import types # UnicodeType from cStringIO import StringIO from mutalyzer import util +from mutalyzer import config + class File() : """ Parse CSV files and spreadsheets. Private variables: - - __config ; Configuration variables. - __output ; The Output object. Special methods: @@ -53,21 +54,16 @@ class File() : and sanitize the output. """ - def __init__(self, config, output) : + def __init__(self, output) : """ Initialise the class. Private variables (altered): - - __config ; Initialised with configuration variables. - __output ; Set to the Output object. - @arg config: Configuration variables - @type config: class instance @arg output: Output object @type output: class instance """ - - self.__config = config self.__output = output #: The Output object #__init__ @@ -106,9 +102,6 @@ class File() : Parse a CSV file. The stream is not rewinded after use. - Private variables: - - __config ; The bufSize configuration variables. - @arg handle: A handle to a stream @type handle: stream @@ -167,7 +160,7 @@ class File() : # I don't think the .seek(0) is needed now we created a new handle new_handle.seek(0) - buf = new_handle.read(self.__config.bufSize) + buf = new_handle.read(config.get('bufSize')) # Default dialect dialect = 'excel' @@ -270,9 +263,6 @@ class File() : - The first and the last element should be non-empty. - The first line should be the header defined in the config file. - Private variables: - - __config ; The header configuration variable. - @todo: Add more new style old style logic @todo: if not inputl: try to make something out of it @@ -289,7 +279,7 @@ class File() : jobl = [(l+1, row) for l, row in enumerate(job)] #TODO: Add more new style old style logic - if jobl[0][1] == self.__config.header : #Old style NameCheckBatch job + if jobl[0][1] == config.get('header') : #Old style NameCheckBatch job ret = [] notthree = [] emptyfield = [] @@ -374,7 +364,7 @@ class File() : err = float(len(errlist))/len(ret) if err == 0: return (ret, columns) - elif err < self.__config.threshold: + elif err < config.get('threshold'): #allow a 5 (default) percent threshold for errors in batchfiles self.__output.addMessage(__file__, 3, "EBPARSE", "There were errors in your batch entry file, they are " @@ -391,19 +381,14 @@ class File() : Get the mime type of a stream by inspecting a fixed number of bytes. The stream is rewinded after use. - Private variables: - - __config: The bufSize configuration variables. - @arg handle: A handle to a stream @type handle: stream @return: The mime type of a file @rtype: string """ - handle.seek(0) - buf = handle.read(self.__config.bufSize) #: The bufSize configuration variables. - + buf = handle.read(config.get('bufSize')) #: The bufSize configuration variables. MagicInstance = magic.open(magic.MAGIC_MIME) MagicInstance.load() diff --git a/mutalyzer/GenRecord.py b/mutalyzer/GenRecord.py index 3c96487220f582f3f076ed45151dda011194faf4..90d50c0f16a67764cc83e49944b9fc8bf04e976d 100644 --- a/mutalyzer/GenRecord.py +++ b/mutalyzer/GenRecord.py @@ -19,6 +19,7 @@ search for them each time. import Bio from mutalyzer import util +from mutalyzer import config from mutalyzer import Crossmap from mutalyzer import Db @@ -379,7 +380,7 @@ class GenRecord() : - checkRecord() ; Check and repair self.record. """ - def __init__(self, output, config) : + def __init__(self, output) : """ Initialise the class. @@ -388,12 +389,8 @@ class GenRecord() : @arg output: an output object @type output: object - @arg config: a config object - @type config: object """ - self.__output = output - self.__config = config self.record = None #__init__ @@ -807,13 +804,13 @@ class GenRecord() : # TODO Also check a range properly. intronPos = abs(transcript.CM.g2x(position)[1]) if intronPos : - if intronPos <= self.__config.spliceAlarm : + if intronPos <= config.get('spliceAlarm'): self.__output.addMessage(__file__, 2, "WSPLICE", "Mutation on splice site in gene %s transcript %s." % ( gene.name, transcript.name)) return #if - if intronPos <= self.__config.spliceWarn : + if intronPos <= config.get('spliceWarn'): self.__output.addMessage(__file__, 2, "WSPLICE", "Mutation near splice site in gene %s transcript %s." % ( gene.name, transcript.name)) diff --git a/mutalyzer/Retriever.py b/mutalyzer/Retriever.py index ded70bcc034d797cbe7a16ff5f2e6b87c706f288..4f5f624cbde53e18456ebcaddd6a5fcf9faef6c5 100644 --- a/mutalyzer/Retriever.py +++ b/mutalyzer/Retriever.py @@ -24,6 +24,7 @@ from xml.dom import DOMException, minidom from xml.parsers import expat from mutalyzer import util +from mutalyzer import config from mutalyzer.parsers import lrg from mutalyzer.parsers import genbank @@ -32,17 +33,10 @@ class Retriever(object) : """ Retrieve a record from either the cache or the NCBI. - Inherited variables from Db.Output.Config: - - email ; The email address which we give to the NCBI. - - cache ; The directory where the records are stored. - - cachesize ; Maximum size of the cache. - Special methods: - - __init__(config, output, database) ; Use variables from the + - __init__(output, database) ; Use variables from the configuration file to initialise the class private variables. - - Private methods: - _foldersize(folder) ; Return the size of a folder. - _cleancache() ; Keep the cache at a maximum size. @@ -67,29 +61,21 @@ class Retriever(object) : - LogMsg(filename, message) ; Log a message. """ - def __init__(self, config, output, database) : + def __init__(self, output, database) : """ Use variables from the configuration file for some simple settings. Make the cache directory if it does not exist yet. - Inherited variables from Db.Output.Config: - - email ; The email address which we give to the NCBI. - - cache ; The directory where the records are stored. - - @arg config: - @type config: @arg output: @type output: @arg database: @type database: """ - - self._config = config self._output = output self._database = database - if not os.path.isdir(self._config.cache) : - os.mkdir(self._config.cache) - Entrez.email = self._config.email + if not os.path.isdir(config.get('cache')) : + os.mkdir(config.get('cache')) + Entrez.email = config.get('email') self.fileType = None #__init__ @@ -119,18 +105,13 @@ class Retriever(object) : First, the cache checked for its size, if it exceeds the maximum size the ``oldest'' files are deleted. Note that accessing a file makes it ``new''. - - Inherited variables from Db.Output.Config: - - cache ; Directory under scrutiny. - - cachesize ; Maximum size of the cache. """ - - if self._foldersize(self._config.cache) < self._config.cachesize: + if self._foldersize(config.get('cache')) < config.get('cachesize'): return # Build a list of files sorted by access time. cachelist = [] - for (path, dirs, files) in os.walk(self._config.cache) : + for (path, dirs, files) in os.walk(config.get('cache')) : for filename in files : filepath = os.path.join(path, filename) cachelist.append( @@ -141,7 +122,7 @@ class Retriever(object) : # small enough (or until the list is exhausted). for i in range(0, len(cachelist)) : os.remove(cachelist[i][1]) - if self._foldersize(self._config.cache) < self._config.cachesize: + if self._foldersize(config.get('cache')) < config.get('cachesize'): break; #for #_cleancache @@ -150,17 +131,13 @@ class Retriever(object) : """ Convert an accession number to a filename. - Inherited variables from Db.Output.Config: - - cache ; Name of the cache directory. - @arg name: The accession number @type name: string @return: A filename @rtype: string """ - - return self._config.cache + '/' + name + "." + self.fileType + ".bz2" + return config.get('cache') + '/' + name + "." + self.fileType + ".bz2" #_nametofile def _write(self, raw_data, filename) : @@ -339,13 +316,12 @@ class GenBankRetriever(Retriever): """ """ - def __init__(self, config, output, database): - # TODO documentation + def __init__(self, output, database): """ + @todo: Documentation. """ - # Recall init of parent - Retriever.__init__(self, config, output, database) + Retriever.__init__(self, output, database) self.fileType = "gb" # Child specific init #__init__ @@ -466,9 +442,6 @@ class GenBankRetriever(Retriever): The content of the slice is placed in the cache with the UD number as filename. - Inherited variables from Db.Output.Config: - - maxDldSize ; Maximum size of the slice. - @arg accno: The accession number of the chromosome @type accno: string @arg start: Start position of the slice @@ -490,7 +463,7 @@ class GenBankRetriever(Retriever): return None # The slice can not be too big. - if stop - start > self._config.maxDldSize : + if stop - start > config.get('maxDldSize'): return None # Check whether we have seen this slice before. @@ -610,23 +583,18 @@ class GenBankRetriever(Retriever): If the downloaded file is recognised by its hash, the old UD number is used. - Inherited variables from Db.Output.Config: - - maxDldSize ; Maximum size of the file. - - minDldSize ; Minimum size of the file. - @arg url: Location of a GenBank record @type url: string @return: UD or None @rtype: string """ - handle = urllib2.urlopen(url) info = handle.info() if info["Content-Type"] == "text/plain" : length = int(info["Content-Length"]) - if length > self._config.minDldSize and \ - length < self._config.maxDldSize : + if length > config.get('minDldSize') and \ + length < config.get('maxDldSize'): raw_data = handle.read() md5sum = self._calcHash(raw_data) UD = self._database.getGBFromHash(md5sum) @@ -756,22 +724,19 @@ class LRGRetriever(Retriever): the cache and return the record. """ - def __init__(self, config, output, database): + def __init__(self, output, database): #TODO documentation """ Initialize the class. @todo: documentation - @arg config: - @type config: @arg output: @type output: @arg database: @type database: """ - # Recall init of parent - Retriever.__init__(self, config, output, database) + Retriever.__init__(self, output, database) self.fileType = "xml" # Child specific init #__init__ @@ -815,9 +780,6 @@ class LRGRetriever(Retriever): grab the file from the confirmed section, if this fails, get it from the pending section. - Inherited variables from Config.Retriever - - lrgURL ; The base url from where LRG files are fetched - @arg name: The name of the LRG file to fetch @type name: string @@ -825,7 +787,7 @@ class LRGRetriever(Retriever): @rtype: string """ - prefix = self._config.lrgURL + prefix = config.get('lrgURL') url = prefix + "%s.xml" % name pendingurl = prefix + "pending/%s.xml" % name @@ -849,10 +811,6 @@ class LRGRetriever(Retriever): """ Download an LRG record from an URL. - Inherited variables from Db.Output.Config: - - maxDldSize ; Maximum size of the file. - - minDldSize ; Minimum size of the file. - @arg url: Location of the LRG record @type url: string @@ -872,7 +830,7 @@ class LRGRetriever(Retriever): if info["Content-Type"] == "application/xml" and info.has_key("Content-length"): length = int(info["Content-Length"]) - if self._config.minDldSize < length < self._config.maxDldSize: + if config.get('minDldSize') < length < config.get('maxDldSize'): raw_data = handle.read() handle.close() diff --git a/mutalyzer/Scheduler.py b/mutalyzer/Scheduler.py index cc10261d93cce18730550b3ae823ff1e177ffadf..ca30875f3fb979e7fcbe948b33cb0d760a2f1a2a 100644 --- a/mutalyzer/Scheduler.py +++ b/mutalyzer/Scheduler.py @@ -20,9 +20,9 @@ import smtplib # smtplib.STMP from email.mime.text import MIMEText # MIMEText import mutalyzer +from mutalyzer import config from mutalyzer import variantchecker from mutalyzer.grammar import Grammar -from mutalyzer.config import Config from mutalyzer.output import Output from mutalyzer.mapping import Converter from mutalyzer import Retriever # Retriever.Retriever @@ -34,7 +34,7 @@ __all__ = ["Scheduler"] class Scheduler() : """ Special methods: - - __init__(config, database) ; + - __init__(database) ; Public methods: - addJob(outputFilter, eMail, queue, fromHost, jobType, Arg1) ; Add a @@ -47,21 +47,16 @@ class Scheduler() : - Batch Position Converter """ - def __init__(self, config, database) : + def __init__(self, database) : #TODO: documentation """ - Initialize the Scheduler, which requires a config object - and a database connection. + Initialize the Scheduler, which requires a database connection. @todo: documentation - @arg config: Config object - @type config: object @arg database: @type database: """ - - self.__config = config self.__database = database self.__run = True #__init__ @@ -89,10 +84,6 @@ class Scheduler() : """ Send an e-mail containing an url to a batch job submitter. - Private variables: - - __config ; The variables mailSubject and mailFrom - are used. - @todo: Handle Connection errors in a try, except clause @arg mailTo: The batch job submitter @@ -127,13 +118,13 @@ Thanks for using Mutalyzer. With kind regards, Mutalyzer batch checker.""" % url) - message["Subject"] = self.__config.mailSubject - message["From"] = self.__config.mailFrom + message["Subject"] = config.get('mailSubject') + message["From"] = config.get('mailFrom') message["To"] = mailTo smtpInstance = smtplib.SMTP() smtpInstance.connect() - smtpInstance.sendmail(self.__config.mailFrom, mailTo, + smtpInstance.sendmail(config.get('mailFrom'), mailTo, message.as_string()) smtpInstance.quit() #__sendMail @@ -364,9 +355,7 @@ Mutalyzer batch checker.""" % url) @arg flags: Flags of the current entry @type flags: """ - - C = Config() - O = Output(__file__, C.Output) + O = Output(__file__) O.addMessage(__file__, -1, "INFO", "Received NameChecker batchvariant " + cmd) @@ -398,12 +387,12 @@ Mutalyzer batch checker.""" % url) outputline += batchOutput[0] #Output - filename = "%s/Results_%s.txt" % (self.__config.resultsDir, i) + filename = "%s/Results_%s.txt" % (config.get('resultsDir'), i) if not os.path.exists(filename) : # If the file does not yet exist, create it with the correct # header above it. The header is read from the config file as # a list. We need a tab delimited string. - header = self.__config.nameCheckOutHeader + header = config.get('nameCheckOutHeader') handle = open(filename, 'a') handle.write("%s\n" % "\t".join(header)) #if @@ -436,9 +425,7 @@ Mutalyzer batch checker.""" % url) @arg flags: Flags of the current entry @type flags: """ - - C = Config() - output = Output(__file__, C.Output) + output = Output(__file__) grammar = Grammar(output) output.addMessage(__file__, -1, "INFO", @@ -457,12 +444,12 @@ Mutalyzer batch checker.""" % url) result = "|".join(output.getBatchMessages(3)) #Output - filename = "%s/Results_%s.txt" % (self.__config.resultsDir, i) + filename = "%s/Results_%s.txt" % (config.get('resultsDir'), i) if not os.path.exists(filename) : # If the file does not yet exist, create it with the correct # header above it. The header is read from the config file as # a list. We need a tab delimited string. - header = self.__config.syntaxCheckOutHeader + header = config.get('syntaxCheckOutHeader') handle = open(filename, 'a') handle.write("%s\n" % "\t".join(header)) #if @@ -499,9 +486,7 @@ Mutalyzer batch checker.""" % url) @arg flags: Flags of the current entry @type flags: """ - - C = Config() - O = Output(__file__, C.Output) + O = Output(__file__) variant = cmd variants = None gName = "" @@ -559,12 +544,12 @@ Mutalyzer batch checker.""" % url) error = "%s" % "|".join(O.getBatchMessages(3)) #Output - filename = "%s/Results_%s.txt" % (self.__config.resultsDir, i) + filename = "%s/Results_%s.txt" % (config.get('resultsDir'), i) if not os.path.exists(filename) : # If the file does not yet exist, create it with the correct # header above it. The header is read from the config file as # a list. We need a tab delimited string. - header = self.__config.positionConverterOutHeader + header = config.get('positionConverterOutHeader') handle = open(filename, 'a') handle.write("%s\n" % "\t".join(header)) #if @@ -598,9 +583,7 @@ Mutalyzer batch checker.""" % url) @arg flags: Flags of the current entry @type flags: """ - - C = Config() - O = Output(__file__, C.Output) + O = Output(__file__) O.addMessage(__file__, -1, "INFO", "Received SNP converter batch rs" + cmd) @@ -610,7 +593,7 @@ Mutalyzer batch checker.""" % url) descriptions = [] if not skip : - R = Retriever.Retriever(C.Retriever, O, None) + R = Retriever.Retriever(O, None) descriptions = R.snpConvert(cmd) # Todo: Is output ok? @@ -619,12 +602,12 @@ Mutalyzer batch checker.""" % url) outputline += "%s\t" % "|".join(O.getBatchMessages(3)) #Output - filename = "%s/Results_%s.txt" % (self.__config.resultsDir, i) + filename = "%s/Results_%s.txt" % (config.get('resultsDir'), i) if not os.path.exists(filename) : # If the file does not yet exist, create it with the correct # header above it. The header is read from the config file as # a list. We need a tab delimited string. - header = self.__config.snpConverterOutHeader + header = config.get('snpConverterOutHeader') handle = open(filename, 'a') handle.write("%s\n" % "\t".join(header)) #if diff --git a/mutalyzer/config.py b/mutalyzer/config.py index cb98f726eaf8cc761243400b8d3bb571fdeda4c9..ae7f8cb0d6520485bf185b0fe07a00dc11c08d58 100644 --- a/mutalyzer/config.py +++ b/mutalyzer/config.py @@ -1,13 +1,26 @@ """ -Module for reading the config file and splitting up the variables into -subclasses. Each of these subclasses are used to configure a specific -module. +Module for reading the configuration values from configuration files. + +All communication with this module should be done by using the get function +which returns a configuration value, given a name. + +Reading the configuration file is implemented lazily and as such done upon the +first call to the get function. + +Configuration values are read from two locations, in this order: +1) /etc/mutalyzer/config +2) $XDG_CONFIG_HOME/mutalyzer/config + +If both files exist, values defined in the second overwrite values defined in +the first. """ import os from configobj import ConfigObj +from mutalyzer.util import singleton + SYSTEM_CONFIGURATION = '/etc/mutalyzer/config' USER_CONFIGURATION = os.path.join( @@ -17,22 +30,36 @@ USER_CONFIGURATION = os.path.join( class ConfigurationError(Exception): + """ + Raised when a configuration file cannot be read. + """ pass -class Config(): +def get(name): + """ + Get a configuration value by name. + + @arg name: Name for the configuration value. + @type name: string + + @raise ConfigurationError: If configuration value could not be read. + Reasons are: + - Configuration file could not be parsed. + - Not all variables are present in configuration file. + - Given configuration value name does not exist. """ - Read the configuration file and store the data in subclasses. + return _Config().get(name) + + +@singleton +class _Config(): """ - class Retriever(): pass - class Db(): pass - class Output(): pass - class Mutator(): pass - class Scheduler(): pass - class Batch(): pass - class File(): pass - class GenRecord(): pass + Read the configuration file and provide access to its values. + Please note the limitations from the use of the @singleton decorator as + described in its docstring. + """ def __init__(self, filename=None): """ Initialise the class with variables read from the configuration @@ -51,10 +78,6 @@ class Config(): is set. In that case, the locations listed above are ignored and the configuration is read from {filename}. - By the DRY-principle, we don't enumerate the configuration variables - for each class in documentation. Instead, what variables are used by - each class is easy to see from the code below. - @kwarg filename: Optional filename to read configuration from. If present, this overrides automatic detection of configuration file location. @@ -85,58 +108,53 @@ class Config(): try: - # Set the variables needed by the Retriever module. - self.Retriever.email = config["email"] - self.Retriever.cache = config["cache"] - self.Retriever.cachesize = int(config["cachesize"]) * 1048576 - self.Retriever.maxDldSize = int(config["maxDldSize"]) * 1048576 - self.Retriever.minDldSize = int(config["minDldSize"]) - self.Retriever.lrgURL = config["lrgurl"] - - # Set the variables needed by the Db module. - self.Db.internalDb = config["internalDb"] - self.Db.dbNames = config["dbNames"] - self.Db.LocalMySQLuser = config["LocalMySQLuser"] - self.Db.LocalMySQLhost = config["LocalMySQLhost"] - - # Set the variables needed by the Output module. - self.Output.log = config["log"] - self.Output.datestring = config["datestring"] - self.Output.loglevel = int(config["loglevel"]) - self.Output.outputlevel = int(config["outputlevel"]) - self.Output.debug = config.as_bool('debug') - - # Set the variables needed by the Mutator module. - self.Mutator.flanksize = int(config["flanksize"]) - self.Mutator.maxvissize = int(config["maxvissize"]) - self.Mutator.flankclipsize = int(config["flankclipsize"]) - - # Set the variables needed by the Scheduler module. - self.Scheduler.mailFrom = config["mailFrom"] - self.Scheduler.mailSubject = config["mailSubject"] - self.Scheduler.resultsDir = config["resultsDir"] - self.Scheduler.nameCheckOutHeader = config["nameCheckOutHeader"] - self.Scheduler.syntaxCheckOutHeader = config["syntaxCheckOutHeader"] - self.Scheduler.positionConverterOutHeader = config["positionConverterOutHeader"] - self.Scheduler.snpConverterOutHeader = config["snpConverterOutHeader"] - - # Set thte variables neede for the Batch module. - self.Batch.PIDfile = config["PIDfile"] - self.Batch.batchInputMaxSize = int(config["batchInputMaxSize"]) * 1048576 - - # Set the variables needed by the File module. - self.File.bufSize = int(config["bufSize"]) - self.File.header = config["header"] - self.File.threshold = float(config["threshold"]) - - # Set the variables needed by the File module. - self.GenRecord.spliceAlarm = int(config["spliceAlarm"]) - self.GenRecord.spliceWarn = int(config["spliceWarn"]) + # We explicitely read all configuration values ad store them in + # our own dictionary. This makes sure we notice missing or + # incorrect values upon instantiation. + + # A few 'special' values. + self._values = {'debug': config.as_bool('debug'), + 'threshold': float(config['threshold'])} + + # Simple string values. + for name in ('email', 'cache', 'lrgurl', 'internalDb', 'dbNames', + 'LocalMySQLuser', 'LocalMySQLhost', 'log', + 'datestring', 'mailFrom', 'mailSubject', + 'resultsDir', 'nameCheckOutHeader', + 'syntaxCheckOutHeader', 'positionConverterOutHeader', + 'snpConverterOutHeader', 'PIDfile', 'header'): + self._values[name] = config[name] + + # Simple integer values. + for name in ('minDldSize', 'loglevel', 'outputlevel', 'flanksize', + 'maxvissize', 'flankclipsize', 'bufSize', + 'spliceAlarm', 'spliceWarn'): + self._values[name] = int(config[name]) + + # File sizes (given in megabytes, stored in bytes). + for name in ('cachesize', 'maxDldSize', 'batchInputMaxSize'): + self._values[name] = int(config[name]) * 1048576 except KeyError as e: raise ConfigurationError('Missing configuration value: %s' % e) #__init__ + def get(self, name): + """ + Get a configuration value by name. + + @arg name: Name for the configuration value. + @type name: string + + @raise ConfigurationError: If given configuration value name does not + exist. + """ + try: + return self._values[name] + except KeyError: + raise ConfigurationError('No such configuration value: %s' % name) + #get + def _load_config(self, filename): """ Create a ConfigObj from the configuration in {filename}. @@ -150,4 +168,4 @@ class Config(): raise ConfigurationError('Could not parse configuration file: %s' \ % filename) #_load_config -#Config +#_Config diff --git a/mutalyzer/mapping.py b/mutalyzer/mapping.py index 28dc5406e9d6760eca3cb98b16e4d215516c063d..584541f5aa993d315eaeef7cf52b8901f3416d80 100644 --- a/mutalyzer/mapping.py +++ b/mutalyzer/mapping.py @@ -41,22 +41,19 @@ class Converter(object) : @todo: Refactor anything using {mutalyzer.models} into the {webservice} module. """ - def __init__(self, build, C, O) : + def __init__(self, build, O) : """ Initialise the class. @arg build: the genome build version of the organism (e.g. hg19 for human genome build version 19) @type build: string - @arg C: crossmapper object - @type C: object @arg O: output object @type O: object """ self.build = None self.__output = O - self.__config = C - self.__database = Db.Mapping(build, C.Db) + self.__database = Db.Mapping(build) # Populated arguments self.parseTree = None @@ -609,17 +606,14 @@ class Updater(object): information into the 'MappingTemp' table. The {merge} method merges this table into the real 'Mapping' table. """ - def __init__(self, build, config): + def __init__(self, build): """ @arg build: Human genome build (or database name), i.e. 'hg18' or 'hg19'. @type build: string - @arg config: A configuration object. - @type config: mutalyzer.config.Config """ self.build = build - self.config = config - self.db = Db.Mapping(build, config.Db) + self.db = Db.Mapping(build) #__init__ def load(self, *args, **kwargs): @@ -649,7 +643,7 @@ class NCBIUpdater(Updater): Example usage: - >>> updater = NCBIUpdater('hg19', mutalyzer.config.Config()) + >>> updater = NCBIUpdater('hg19') >>> updater.load('/tmp/seq_gene.md', 'GRCh37.p2-Primary Assembly') >>> updater.merge() @@ -659,16 +653,14 @@ class NCBIUpdater(Updater): 'feature_name', 'feature_id', 'feature_type', 'group_label', 'transcript', 'evidence_code'] - def __init__(self, build, config): + def __init__(self, build): """ @arg build: Human genome build (or database name), i.e. 'hg18' or 'hg19'. @type build: string - @arg config: A configuration object. - @type config: mutalyzer.config.Config """ self.exon_backlog = {} - super(NCBIUpdater, self).__init__(build, config) + super(NCBIUpdater, self).__init__(build) #__init__ def load(self, mapping_file, assembly): diff --git a/mutalyzer/mutator.py b/mutalyzer/mutator.py index 9065205016dfb634fd5c24f3d115f0a5285ba491..2a59c8b7db5ed6bfa360963ce302e07a4cceaa4c 100644 --- a/mutalyzer/mutator.py +++ b/mutalyzer/mutator.py @@ -12,12 +12,14 @@ The original as well as the mutated string are stored here. """ -from mutalyzer import util from Bio import Restriction from Bio.Seq import Seq from Bio.Alphabet.IUPAC import IUPACAmbiguousDNA from Bio.Seq import reverse_complement +from mutalyzer import util +from mutalyzer import config + class Mutator() : """ @@ -28,7 +30,6 @@ class Mutator() : 'addedRestrictionSites' respectively. Private variables: - - __config ; Configuration variables of this class. - __output ; The output object. - __shift ; A sorted list of tuples (position, shiftsize) where the modifications in length are stored. @@ -72,13 +73,11 @@ class Mutator() : position pos1 to pos2. """ - def __init__(self, orig, config, output) : + def __init__(self, orig, output) : """ Initialise the class with the original string. Private variables (altered): - - __config ; Initialised with the configuration - variables. - __output ; Initialised with the output object. - __shift ; Initialised to the empty list. - __restrictionBatch ; Initialised to a default set of @@ -90,13 +89,9 @@ class Mutator() : @arg orig: The original string before mutation @type orig: string - @arg config: Configuration variables - @type config: object @arg output: The output object @type output: object """ - - self.__config = config self.__output = output self.__shift = [] self.__removed_sites = set() @@ -214,8 +209,6 @@ class Mutator() : we perform the alteration. Private variables: - - __config ; The variables maxvissize, flanksize and flankclipsize - are used in the visualisation. - __output ; Visualisation information is added. Public variables (altered): @@ -237,8 +230,8 @@ class Mutator() : # This part is for visualisation. # - loflank = self.orig[max(pos1 - self.__config.flanksize, 0):pos1] - roflank = self.orig[pos2:pos2 + self.__config.flanksize] + loflank = self.orig[max(pos1 - config.get('flanksize'), 0):pos1] + roflank = self.orig[pos2:pos2 + config.get('flanksize')] delPart = self.orig[pos1:pos2] #odel = delPart #if len(odel) > self.__config.maxvissize : @@ -249,8 +242,8 @@ class Mutator() : bp1 = self.shiftpos(pos1) bp2 = self.shiftpos(pos2) - lmflank = self.mutated[max(bp1 - self.__config.flanksize, 0):bp1] - rmflank = self.mutated[bp2:bp2 + self.__config.flanksize] + lmflank = self.mutated[max(bp1 - config.get('flanksize'), 0):bp1] + rmflank = self.mutated[bp2:bp2 + config.get('flanksize')] #insvis = ins #if len(ins) > self.__config.maxvissize : @@ -304,10 +297,10 @@ class Mutator() : @rtype: string """ - if len(string) > self.__config.maxvissize : - return "%s [%ibp] %s" % (string[:self.__config.flankclipsize], - len(string) - self.__config.flankclipsize * 2, - string[-self.__config.flankclipsize:]) + if len(string) > config.get('maxvissize'): + return "%s [%ibp] %s" % (string[:config.get('flankclipsize')], + len(string) - config.get('flankclipsize') * 2, + string[-config.get('flankclipsize'):]) return string #visualiseIns diff --git a/mutalyzer/output.py b/mutalyzer/output.py index 53bedeed5aa127318bfdfdb3f41535e2b011effd..04d552b1d0bdc8186183785319a68544bee8676f 100644 --- a/mutalyzer/output.py +++ b/mutalyzer/output.py @@ -26,6 +26,7 @@ Public classes: import time from mutalyzer import util +from mutalyzer import config from mutalyzer.models import SoapMessage @@ -34,7 +35,6 @@ class Output() : Provide an output interface for errors, warnings and logging purposes. Private variables: - - __config ; Configuration variables. - __outputdata ; The output dictionary. - __messages ; The messages list. - __instance ; The name of the module that made this object. @@ -43,10 +43,9 @@ class Output() : - __warnings ; The number of warnings that have been processed. Special methods: - - __init__(instance, config) ; Initialise the class with variables - from the config file and the calling - module. - - __del__() ; Close the logfile and clean up. + - __init__(instance) ; Initialise the class with the calling + module. + - __del__() ; Close the logfile and clean up. Public methods: - addMessage(filename, level, code, description) ; Add a message to @@ -59,13 +58,11 @@ class Output() : and warnings. """ - def __init__(self, instance, config) : + def __init__(self, instance): """ - Initialise the class private variables with variables from the - config file and the calling module. + Initialise the class with the calling module. Private variables (altered): - - __config ; Configuration variables. - __outputdata ; The output dictionary. - __messages ; The messages list. - __instance ; Initialised with the name of the module that @@ -77,15 +74,11 @@ class Output() : @arg instance: The filename of the module that created this object @type instance: string - @arg config: The configuration object - @type config: object """ - - self.__config = config self.__outputData = {} self.__messages = [] self.__instance = util.nice_filename(instance) - self.__loghandle = open(self.__config.log, "a+") + self.__loghandle = open(config.get('log'), "a+") self.__errors = 0 self.__warnings = 0 #__init__ @@ -120,7 +113,6 @@ class Output() : Private variables: - __messages ; The messages list. - __instance ; Module that created the Output object. - - __config ; The variables loglevel and datestring are used. - __loghandle ; Handle to the log file. Private variables (altered): @@ -145,9 +137,9 @@ class Output() : # Log the message if the message is important enough, or if it is only # meant to be logged (level -1). - if level >= self.__config.loglevel or level == -1 : + if level >= config.get('loglevel') or level == -1 : self.__loghandle.write(time.strftime( - self.__config.datestring + ' ') + "%s (%s) %s: %s: %s\n" % ( + config.get('datestring') + ' ') + "%s (%s) %s: %s: %s\n" % ( self.__instance, nice_name, code, message.named_level(), description)) self.__loghandle.flush() @@ -160,12 +152,11 @@ class Output() : Private variables: - __messages ; The messages list. - - __config ; The variable outputlevel is used. @return: A list of messages @rtype: list """ - return filter(lambda m: m.level >= self.__config.outputlevel, + return filter(lambda m: m.level >= config.get('outputlevel'), self.__messages) #getMessages diff --git a/mutalyzer/parsers/genbank.py b/mutalyzer/parsers/genbank.py index 060e9a5277c5e35c02cf5667f2daf9366e2de725..8f640f618c72b37bd16c1f513cc626943c8e6651 100644 --- a/mutalyzer/parsers/genbank.py +++ b/mutalyzer/parsers/genbank.py @@ -8,7 +8,7 @@ import bz2 from Bio import SeqIO, Entrez from Bio.Alphabet import ProteinAlphabet -from mutalyzer.config import Config +from mutalyzer import config from mutalyzer import Db from mutalyzer.GenRecord import PList, Locus, Gene, Record, GenRecord @@ -52,17 +52,11 @@ class GBparser(): """ Initialise the class - Public variables: - - config ; Config object. - Private variables: - __database ; Db.Cache object - - @requires: Config """ - config = Config() - Entrez.email = config.Retriever.email - self.__database = Db.Cache(config.Db) + Entrez.email = config.get('email') + self.__database = Db.Cache() #__init__ def __location2pos(self, location): diff --git a/mutalyzer/sync.py b/mutalyzer/sync.py index 2a96446bf2b268e284c1a9b0db6dca4349c20d27..ae3622b33732386cf196e3bbf4174920903246d0 100644 --- a/mutalyzer/sync.py +++ b/mutalyzer/sync.py @@ -11,6 +11,7 @@ from datetime import datetime, timedelta import urllib2 from suds.client import Client +from mutalyzer import config from mutalyzer import Retriever @@ -21,18 +22,15 @@ class CacheSync(object): """ Synchronize the database cache with other Mutalyzer instances. """ - def __init__(self, config, output, database): + def __init__(self, output, database): """ Instantiate the object. - @arg config: A configuration object. - @type config: mutalyzer.config.Config.Retriever @arg output: An output object. @type output: mutalyzer.output.Output @arg database: A database object. @type database: mutalyzer.Db.Cache """ - self._config = config self._output = output self._database = database @@ -60,7 +58,7 @@ class CacheSync(object): for entry in entries: # Note that this way we only include Genbank files, not LRG files. cached = None - if os.path.isfile(os.path.join(self._config.cache, + if os.path.isfile(os.path.join(config.get('cache'), '%s.gb.bz2' % entry[0])): cached = '%s.gb' % entry[0] cache.append({'name': entry[0], @@ -135,9 +133,7 @@ class CacheSync(object): handle.close() # Store remote data - retriever = Retriever.GenBankRetriever(self._config, - self._output, - self._database) + retriever = Retriever.GenBankRetriever(self._output, self.database) retriever.write(data, name, 0) def sync_with_remote(self, remote_wsdl, url_template, diff --git a/mutalyzer/util.py b/mutalyzer/util.py index 0918d4c2af139fba75c0a71d2d12c5fc8e9aed31..8738bbca0ee1650fb0ea9517a45be36c117d5b3a 100644 --- a/mutalyzer/util.py +++ b/mutalyzer/util.py @@ -1,20 +1,20 @@ """ General utility functions. -@todo: All these functions come from the old Mutalyzer.py file. Try to find - general utility functions in other modules too. +@todo: Most of these functions come from the old Mutalyzer.py file. Try to + find general utility functions in other modules too. @todo: Use exceptions for failure handling. @todo: End vs stop. I guess we should use start/stop (end goes with beginning). - Or first/last, or acceptor/donor. Anyway, CDS is always denoted with - start/stop. Important thing is that the semantics should be clear. - Idea: - * CDS -> use start/stop - * splice sites or exons -> acceptor/donor - * translation -> begin/end - * any range of bases -> first/last - * interbase position (if two numbers are used) -> before/after + Or first/last, or acceptor/donor. Anyway, CDS is always denoted with + start/stop. Important thing is that the semantics should be clear. + Idea: + * CDS -> use start/stop + * splice sites or exons -> acceptor/donor + * translation -> begin/end + * any range of bases -> first/last + * interbase position (if two numbers are used) -> before/after @todo: We can also group this in separate files in a util/ directory, according - to function (e.g. util/sequences.py, util/positioning.py, etc). + to function (e.g. util/sequences.py, util/positioning.py, etc). @todo: Unit tests (some can directly be extracted from the docstring). """ @@ -788,6 +788,27 @@ def skip(f): #skip +def singleton(cls): + """ + Decorator to define a class with a singleton instance. + + Note that this decorator makes cls a function instead of a class and + things like super() and classmethods won't work anymore. So be carefull + with this and certainly don't use it with subclassing. + + By Shane Hathaway, taken from PEP318 [1]. + + [1] http://www.python.org/dev/peps/pep-0318/#examples + """ + instances = {} + def getinstance(): + if cls not in instances: + instances[cls] = cls() + return instances[cls] + return getinstance +#singleton + + def monkey_patch_suds(): """ Apply our monkey-patch for the suds package. diff --git a/mutalyzer/variantchecker.py b/mutalyzer/variantchecker.py index 8b7eb9e7091513288f413a604fc14a70df517a64..7ece5cbe3c72d025b7506077baba375742296937 100644 --- a/mutalyzer/variantchecker.py +++ b/mutalyzer/variantchecker.py @@ -1432,7 +1432,7 @@ def process_variant(mutator, description, record, output): #process_variant -def check_variant(description, config, output): +def check_variant(description, output): """ Check the variant described by {description} according to the HGVS variant nomenclature and populate the {output} object with various information @@ -1440,8 +1440,6 @@ def check_variant(description, config, output): @arg description: Variant description in HGVS notation. @type description: string - @arg config: A configuration object. - @type config: Modules.Config.Config @arg output: An output object. @type output: Modules.Output.Output @@ -1471,12 +1469,12 @@ def check_variant(description, config, output): gene_symbol = transcript_id = '' - database = Db.Cache(config.Db) + database = Db.Cache() if parsed_description.LrgAcc: filetype = 'LRG' record_id = parsed_description.LrgAcc transcript_id = parsed_description.LRGTranscriptID - retriever = Retriever.LRGRetriever(config.Retriever, output, database) + retriever = Retriever.LRGRetriever(output, database) else: filetype = 'GB' if parsed_description.Gene: @@ -1485,8 +1483,7 @@ def check_variant(description, config, output): if parsed_description.Gene.ProtIso: output.addMessage(__file__, 4, 'EPROT', 'Indexing by ' \ 'protein isoform is not supported.') - retriever = Retriever.GenBankRetriever(config.Retriever, output, - database) + retriever = Retriever.GenBankRetriever(output, database) retrieved_record = retriever.loadrecord(record_id) @@ -1506,7 +1503,7 @@ def check_variant(description, config, output): output.addOutput('preColon', description.split(':')[0]) output.addOutput('variant', description.split(':')[-1]) - record = GenRecord.GenRecord(output, config.GenRecord) + record = GenRecord.GenRecord(output) record.record = retrieved_record record.checkRecord() @@ -1530,7 +1527,7 @@ def check_variant(description, config, output): # Note: The GenRecord instance is carrying the sequence in .record.seq. # So is the Mutator instance in .mutator.orig. - mutator = Mutator(record.record.seq, config.Mutator, output) + mutator = Mutator(record.record.seq, output) # Todo: If processing of the variant fails, we might still want to show # information about the record, gene, transcript. diff --git a/mutalyzer/webservice.py b/mutalyzer/webservice.py index e969c04249cd6a823e57662a28edc77808a3ebe8..4c87b5e901a0fe994b00ad9537c77f84a31fc1e5 100644 --- a/mutalyzer/webservice.py +++ b/mutalyzer/webservice.py @@ -32,7 +32,7 @@ import socket from operator import itemgetter, attrgetter import mutalyzer -from mutalyzer.config import Config +from mutalyzer import config from mutalyzer.output import Output from mutalyzer.grammar import Grammar from mutalyzer.sync import CacheSync @@ -51,7 +51,6 @@ class MutalyzerService(DefinitionBase): These methods are made public via a SOAP interface. """ def __init__(self, environ=None): - self._config = Config() super(MutalyzerService, self).__init__(environ) #__init__ @@ -68,7 +67,7 @@ class MutalyzerService(DefinitionBase): @type build: string """ - if not build in self._config.Db.dbNames : + if not build in config.get('dbNames'): L.addMessage(__file__, 4, "EARG", "EARG %s" % build) raise Fault("EARG", "The build argument (%s) was not a valid " \ @@ -162,14 +161,14 @@ class MutalyzerService(DefinitionBase): @return: A list of transcripts. @rtype: list """ - L = Output(__file__, self._config.Output) + L = Output(__file__) L.addMessage(__file__, -1, "INFO", "Received request getTranscripts(%s %s %s %s)" % (build, chrom, pos, versions)) self.__checkBuild(L, build) - D = Db.Mapping(build, self._config.Db) + D = Db.Mapping(build) self.__checkChrom(L, D, chrom) self.__checkPos(L, pos) @@ -198,14 +197,14 @@ class MutalyzerService(DefinitionBase): """ Todo: documentation. """ - L = Output(__file__, self._config.Output) + L = Output(__file__) L.addMessage(__file__, -1, "INFO", "Received request getTranscriptsByGene(%s %s)" % (build, name)) self.__checkBuild(L, build) - D = Db.Mapping(build, self._config.Db) + D = Db.Mapping(build) ret = D.get_TranscriptsByGeneName(name) @@ -244,13 +243,13 @@ class MutalyzerService(DefinitionBase): @return: A list of transcripts. @rtype: list """ - L = Output(__file__, self._config.Output) + L = Output(__file__) L.addMessage(__file__, -1, "INFO", "Received request getTranscriptsRange(%s %s %s %s %s)" % (build, chrom, pos1, pos2, method)) - D = Db.Mapping(build, self._config.Db) + D = Db.Mapping(build) self.__checkBuild(L, build) ret = D.get_Transcripts(chrom, pos1, pos2, method) @@ -279,12 +278,12 @@ class MutalyzerService(DefinitionBase): @return: The name of the associated gene. @rtype: string """ - L = Output(__file__, self._config.Output) + L = Output(__file__) L.addMessage(__file__, -1, "INFO", "Received request getGeneName(%s %s)" % (build, accno)) - D = Db.Mapping(build, self._config.Db) + D = Db.Mapping(build) self.__checkBuild(L, build) ret = D.get_GeneName(accno.split('.')[0]) @@ -338,13 +337,13 @@ class MutalyzerService(DefinitionBase): - type ; The mutation type. @rtype: object """ - L = Output(__file__, self._config.Output) + L = Output(__file__) L.addMessage(__file__, -1, "INFO", "Reveived request mappingInfo(%s %s %s %s)" % ( LOVD_ver, build, accNo, variant)) - conv = Converter(build, self._config, L) + conv = Converter(build, L) result = conv.mainMapping(accNo, variant) L.addMessage(__file__, -1, "INFO", @@ -376,13 +375,13 @@ class MutalyzerService(DefinitionBase): - CDS_stop ; CDS stop in I{c.} notation. @rtype: object """ - O = Output(__file__, self._config.Output) + O = Output(__file__) O.addMessage(__file__, -1, "INFO", "Received request transcriptInfo(%s %s %s)" % (LOVD_ver, build, accNo)) - converter = Converter(build, self._config, O) + converter = Converter(build, O) T = converter.mainTranscript(accNo) O.addMessage(__file__, -1, "INFO", @@ -404,8 +403,8 @@ class MutalyzerService(DefinitionBase): @return: The accession number of a chromosome. @rtype: string """ - D = Db.Mapping(build, self._config.Db) - L = Output(__file__, self._config.Output) + D = Db.Mapping(build) + L = Output(__file__) L.addMessage(__file__, -1, "INFO", "Received request chromAccession(%s %s)" % (build, name)) @@ -436,8 +435,8 @@ class MutalyzerService(DefinitionBase): @return: The name of a chromosome. @rtype: string """ - D = Db.Mapping(build, self._config.Db) - L = Output(__file__, self._config.Output) + D = Db.Mapping(build) + L = Output(__file__) L.addMessage(__file__, -1, "INFO", "Received request chromName(%s %s)" % (build, accNo)) @@ -468,8 +467,8 @@ class MutalyzerService(DefinitionBase): @return: The name of a chromosome. @rtype: string """ - D = Db.Mapping(build, self._config.Db) - L = Output(__file__, self._config.Output) + D = Db.Mapping(build) + L = Output(__file__) L.addMessage(__file__, -1, "INFO", "Received request getchromName(%s %s)" % (build, acc)) @@ -504,12 +503,12 @@ class MutalyzerService(DefinitionBase): @return: The variant(s) in either I{g.} or I{c.} notation. @rtype: list """ - D = Db.Mapping(build, self._config.Db) - O = Output(__file__, self._config.Output) + D = Db.Mapping(build) + O = Output(__file__) O.addMessage(__file__, -1, "INFO", "Received request cTogConversion(%s %s)" % ( build, variant)) - converter = Converter(build, self._config, O) + converter = Converter(build, O) variant = converter.correctChrVariant(variant) if "c." in variant : @@ -539,7 +538,7 @@ class MutalyzerService(DefinitionBase): - messages: List of (error) messages as strings. @rtype: object """ - output = Output(__file__, self._config.Output) + output = Output(__file__) output.addMessage(__file__, -1, "INFO", "Received request checkSyntax(%s)" % (variant)) @@ -569,10 +568,10 @@ class MutalyzerService(DefinitionBase): """ Todo: documentation. """ - O = Output(__file__, self._config.Output) + O = Output(__file__) O.addMessage(__file__, -1, "INFO", "Received request runMutalyzer(%s)" % (variant)) - variantchecker.check_variant(variant, self._config, O) + variantchecker.check_variant(variant, O) result = MutalyzerOutput() @@ -630,16 +629,16 @@ class MutalyzerService(DefinitionBase): """ Todo: documentation. """ - O = Output(__file__, self._config.Output) - D = Db.Cache(self._config.Db) + O = Output(__file__) + D = Db.Cache() O.addMessage(__file__, -1, "INFO", "Received request getGeneAndTranscript(%s, %s)" % (genomicReference, transcriptReference)) - retriever = Retriever.GenBankRetriever(self._config.Retriever, O, D) + retriever = Retriever.GenBankRetriever(O, D) record = retriever.loadrecord(genomicReference) - GenRecordInstance = GenRecord.GenRecord(O, self._config.GenRecord) + GenRecordInstance = GenRecord.GenRecord(O) GenRecordInstance.record = record GenRecordInstance.checkRecord() @@ -696,16 +695,16 @@ class MutalyzerService(DefinitionBase): - id - product """ - O = Output(__file__, self._config.Output) - D = Db.Cache(self._config.Db) + O = Output(__file__) + D = Db.Cache() O.addMessage(__file__, -1, "INFO", "Received request getTranscriptsAndInfo(%s)" % genomicReference) - retriever = Retriever.GenBankRetriever(self._config.Retriever, O, D) + retriever = Retriever.GenBankRetriever(O, D) record = retriever.loadrecord(genomicReference) # Todo: If loadRecord failed (e.g. DTD missing), we should abort here. - GenRecordInstance = GenRecord.GenRecord(O, self._config.GenRecord) + GenRecordInstance = GenRecord.GenRecord(O) GenRecordInstance.record = record GenRecordInstance.checkRecord() @@ -810,9 +809,9 @@ class MutalyzerService(DefinitionBase): """ Todo: documentation, error handling, argument checking, tests. """ - O = Output(__file__, self._config.Output) - D = Db.Cache(self._config.Db) - retriever = Retriever.GenBankRetriever(self._config.Retriever, O, D) + O = Output(__file__) + D = Db.Cache() + retriever = Retriever.GenBankRetriever(O, D) O.addMessage(__file__, -1, "INFO", "Received request sliceChromosomeByGene(%s, %s, %s, %s)" % ( @@ -839,9 +838,9 @@ class MutalyzerService(DefinitionBase): """ Todo: documentation, error handling, argument checking, tests. """ - O = Output(__file__, self._config.Output) - D = Db.Cache(self._config.Db) - retriever = Retriever.GenBankRetriever(self._config.Retriever, O, D) + O = Output(__file__) + D = Db.Cache() + retriever = Retriever.GenBankRetriever(O, D) O.addMessage(__file__, -1, "INFO", "Received request sliceChromosome(%s, %s, %s, %s)" % ( @@ -875,7 +874,7 @@ class MutalyzerService(DefinitionBase): - contactEmail: The email address to contact for more information. @rtype: object """ - output = Output(__file__, self._config.Output) + output = Output(__file__) output.addMessage(__file__, -1, 'INFO', 'Received request info') result = InfoOutput() @@ -913,13 +912,13 @@ class MutalyzerService(DefinitionBase): This method is intended to be used by Mutalyzer itself to synchronize the cache between installations on different servers. """ - output = Output(__file__, self._config.Output) + output = Output(__file__) output.addMessage(__file__, -1, 'INFO', 'Received request getCache') - database = Db.Cache(self._config.Db) - sync = CacheSync(self._config.Retriever, output, database) + database = Db.Cache() + sync = CacheSync(output, database) cache = sync.local_cache(created_since) @@ -948,12 +947,12 @@ class MutalyzerService(DefinitionBase): @return: List of HGVS descriptions. @rtype: list(string) """ - output = Output(__file__, self._config.Output) + output = Output(__file__) output.addMessage(__file__, -1, 'INFO', 'Received request getdbSNPDescription(%s)' % rs_id) - retriever = Retriever.Retriever(self._config.Retriever, output, None) + retriever = Retriever.Retriever(output, None) descriptions = retriever.snpConvert(rs_id) output.addMessage(__file__, -1, 'INFO', diff --git a/mutalyzer/website.py b/mutalyzer/website.py index 03e946a009d4f57862e9102551c3e537b4bf63e5..bd3328a01236949ddf6b0692404876d96c0a3248 100644 --- a/mutalyzer/website.py +++ b/mutalyzer/website.py @@ -30,7 +30,7 @@ from simpletal import simpleTAL import mutalyzer from mutalyzer import util -from mutalyzer.config import Config +from mutalyzer import config from mutalyzer.grammar import Grammar from mutalyzer import webservice from mutalyzer import variantchecker @@ -42,12 +42,8 @@ from mutalyzer import Retriever from mutalyzer import File -# Load configuration from configuration file -config = Config() - - # Show web.py debugging information. -web.config.debug = config.Output.debug +web.config.debug = config.get('debug') # URL dispatch table @@ -167,7 +163,7 @@ render = render_tal(os.path.join(mutalyzer.package_root(), 'templates'), 'nomenclatureVersion': mutalyzer.NOMENCLATURE_VERSION, 'releaseDate': mutalyzer.__date__, 'release': mutalyzer.RELEASE, - 'contactEmail': config.Retriever.email}) + 'contactEmail': config.get('email')}) # web.py application app = web.application(urls, globals(), autoreload=False) @@ -240,7 +236,7 @@ class Downloads: if not os.path.isfile(file_path): raise web.notfound() handle = open(file_path) - F = File.File(config.File, None) + F = File.File(None) web.header('Content-Type', F.getMimeType(handle)[0]) web.header('Content-Disposition', 'attachment; filename="%s"' % file) return handle.read() @@ -263,7 +259,7 @@ class Reference: The url routing currently makes sure to only call this with filenames of the form [a-zA-Z\._-]+. """ - file_path = os.path.join(config.Retriever.cache, '%s.bz2' % file) + file_path = os.path.join(config.get('cache'), '%s.bz2' % file) if not os.path.isfile(file_path): raise web.notfound() handle = bz2.BZ2File(file_path, 'r') @@ -286,7 +282,7 @@ class Reference: reconstructed from the information in the database. Because if the latter is the case, Mutalyzer will add it to the cache on the fly. """ - file_path = os.path.join(config.Retriever.cache, '%s.bz2' % file) + file_path = os.path.join(config.get('cache'), '%s.bz2' % file) if not os.path.isfile(file_path): # The following is a hack to return a 404 not found status with # empty body (as is checked by our unit test framework, WebTest). @@ -325,7 +321,7 @@ class GetGS: @return: Output of name checker if forward is set, otherwise the GeneSymbol with the variant notation as string. """ - O = Output(__file__, config.Output) + output = Output(__file__) i = web.input(mutationName=None, variantRecord=None, forward=None) @@ -333,11 +329,9 @@ class GetGS: # We stringify the variant, because a unicode string crashes # Bio.Seq.reverse_complement in mapping.py:607. - # We are only interested in the legend - #Mutalyzer.process(str(i.mutationName), config, O) - variantchecker.check_variant(str(i.mutationName), config, O) + variantchecker.check_variant(str(i.mutationName), output) - legends = O.getOutput("legends") + legends = output.getOutput("legends") # Filter the transcript from the legend legends = [l for l in legends if "_v" in l[0]] @@ -378,7 +372,7 @@ class SyntaxCheck: Parameters: - variant: Variant name to check. """ - output = Output(__file__, config.Output) + output = Output(__file__) i = web.input() variant = i.variant if variant.find(',') >= 0: @@ -431,13 +425,13 @@ class Snp: @kwarg rs_id: The dbSNP rs number (including 'rs' prefix). @type rs_id: string """ - output = Output(__file__, config.Output) + output = Output(__file__) descriptions = [] if rs_id: output.addMessage(__file__, -1, 'INFO', 'Received %s' % rs_id) - retriever = Retriever.Retriever(config.Retriever, output, None) + retriever = Retriever.Retriever(output, None) descriptions = retriever.snpConvert(rs_id) output.addMessage(__file__, -1, 'INFO', 'Finished processing %s' % rs_id) @@ -484,9 +478,9 @@ class PositionConverter: @kwarg build: Human genome build (currently 'hg18' or 'hg19'). @kwarg variant: Variant to convert. """ - output = Output(__file__, config.Output) + output = Output(__file__) - avail_builds = config.Db.dbNames[::-1] + avail_builds = config.get('dbNames')[::-1] if build : avail_builds.remove(build) @@ -503,7 +497,7 @@ class PositionConverter: } if build and variant: - converter = Converter(build, config, output) + converter = Converter(build, output) #Convert chr accNo to NC number variant = converter.correctChrVariant(variant) @@ -589,13 +583,13 @@ class VariantInfo: acc = i.acc var = i.var - output = Output(__file__, config.Output) + output = Output(__file__) output.addMessage(__file__, -1, 'INFO', 'Received %s:%s (LOVD_ver %s, build %s)' \ % (acc, var, LOVD_ver, build)) - converter = Converter(build, config, output) + converter = Converter(build, output) result = '' @@ -682,7 +676,7 @@ class Check: @kwarg interactive: Run interactively, meaning we wrap the result in the site layout and include the HTML form. """ - output = Output(__file__, config.Output) + output = Output(__file__) args = { 'lastpost' : name @@ -695,7 +689,7 @@ class Check: # Todo: The following is probably a problem elsewhere too. # We stringify the variant, because a unicode string crashes # Bio.Seq.reverse_complement in mapping.py:607. - variantchecker.check_variant(str(name), config, output) + variantchecker.check_variant(str(name), output) output.addMessage(__file__, -1, 'INFO', 'Finished processing variant %s' % name) @@ -814,7 +808,7 @@ class BatchProgress: total = int(i.totalJobs) except ValueError: return - D = Db.Batch(config.Db) + D = Db.Batch() left = D.entriesLeftForJob(jobID) percentage = int(100 - (100 * left / float(total))) if i.ajax: @@ -876,9 +870,9 @@ class BatchChecker: (default), 'SyntaxChecker', 'PositionConverter', or 'SnpConverter'. """ - O = Output(__file__, config.Output) + O = Output(__file__) - maxUploadSize = config.Batch.batchInputMaxSize + maxUploadSize = config.get('batchInputMaxSize') attr = {"messages" : [], "errors" : [], @@ -891,7 +885,7 @@ class BatchChecker: "hideTypes" : batchType and 'none' or '', "selected" : "0", "batchType" : batchType or "", - "avail_builds" : config.Db.dbNames[::-1], + "avail_builds" : config.get('dbNames')[::-1], "jobID" : None, "totalJobs" : None } @@ -923,9 +917,9 @@ class BatchChecker: web.ctx.status = '413 Request entity too large' return 'Sorry, only files up to %s megabytes are accepted.' % (float(maxUploadSize) / 1048576) - D = Db.Batch(config.Db) - S = Scheduler.Scheduler(config.Scheduler, D) - FileInstance = File.File(config.File, O) + D = Db.Batch() + S = Scheduler.Scheduler(D) + FileInstance = File.File(O) # Generate the fromhost URL from which the results can be fetched fromHost = web.ctx.homedomain + web.ctx.homepath + '/' @@ -970,7 +964,7 @@ class BatchResult: of the form \d+. """ filename = 'Results_%s.txt' % result - handle = open(os.path.join(config.Scheduler.resultsDir, filename)) + handle = open(os.path.join(config.get('resultsDir'), filename)) web.header('Content-Type', 'text/plain') web.header('Content-Disposition', 'attachment; filename="%s"' % filename) @@ -1020,7 +1014,7 @@ class Uploader: """ Render reference sequence uploader form. """ - maxUploadSize = config.Retriever.maxDldSize + maxUploadSize = config.get('maxDldSize') UD, errors = "", [] args = { "UD" : UD, @@ -1063,11 +1057,11 @@ class Uploader: - stop: Stop position. - orientation: Orientation. """ - maxUploadSize = config.Retriever.maxDldSize + maxUploadSize = config.get('maxDldSize') - O = Output(__file__, config.Output) - D = Db.Cache(config.Db) - R = Retriever.GenBankRetriever(config.Retriever, O, D) + O = Output(__file__) + D = Db.Cache() + R = Retriever.GenBankRetriever(O, D) UD, errors = "", [] diff --git a/tests/test_grammar.py b/tests/test_grammar.py index 8aadc2a0c3a296736684d4550c01e3f190fdb9a8..3cc5c4255d432f3a549a7729e256748f7445bd3d 100644 --- a/tests/test_grammar.py +++ b/tests/test_grammar.py @@ -8,7 +8,6 @@ import os from nose.tools import * import mutalyzer -from mutalyzer.config import Config from mutalyzer.grammar import Grammar from mutalyzer.output import Output @@ -22,8 +21,7 @@ class TestGrammar(): """ Initialize test Grammar instance. """ - self.config = Config() - self.output = Output(__file__, self.config.Output) + self.output = Output(__file__) self.grammar = Grammar(self.output) def test_some_variants(self): diff --git a/tests/test_mapping.py b/tests/test_mapping.py index 036b46f6c7aadc2ca26629cc123fa7b01c9a4869..5c7b38c69e77fce9965841c189f52c58c076812d 100644 --- a/tests/test_mapping.py +++ b/tests/test_mapping.py @@ -6,7 +6,6 @@ Tests for the mapping module. #import logging; logging.basicConfig() from nose.tools import * -from mutalyzer.config import Config from mutalyzer.output import Output from mutalyzer.mapping import Converter @@ -19,14 +18,13 @@ class TestConverter(): """ Initialize test converter module. """ - self.config = Config() - self.output = Output(__file__, self.config.Output) + self.output = Output(__file__) def _converter(self, build): """ Create a Converter instance for a given build. """ - return Converter(build, self.config, self.output) + return Converter(build, self.output) def test_converter(self): """ diff --git a/tests/test_mutator.py b/tests/test_mutator.py index ee01cf2a1f0a0ea04af396d5d458511159cfd932..89579e70b049dc253e94604d85bd6e1f28b9b059 100644 --- a/tests/test_mutator.py +++ b/tests/test_mutator.py @@ -12,7 +12,6 @@ from Bio.Seq import Seq import mutalyzer from mutalyzer.util import skip -from mutalyzer.config import Config from mutalyzer.output import Output from mutalyzer import mutator @@ -36,16 +35,13 @@ class TestMutator(): """ Initialize test mutator module. """ - self.config = Config() - self.output = Output(__file__, self.config.Output) + self.output = Output(__file__) def _mutator(self, sequence): """ Create a Mutator instance for a given sequence. """ - return mutator.Mutator(sequence, - self.config.Mutator, - self.output) + return mutator.Mutator(sequence, self.output) def test_shiftpos_no_change(self): """ diff --git a/tests/test_variantchecker.py b/tests/test_variantchecker.py index 74bbae733b93b4caadcb097559de70ffa3b211fc..c665150dd10bffe948fe45d0c3fee48798d836ec 100644 --- a/tests/test_variantchecker.py +++ b/tests/test_variantchecker.py @@ -6,7 +6,6 @@ Tests for the variantchecker module. #import logging; logging.basicConfig() from nose.tools import * -from mutalyzer.config import Config from mutalyzer.output import Output from mutalyzer.variantchecker import check_variant @@ -19,16 +18,14 @@ class TestVariantchecker(): """ Initialize test variantchecker module. """ - self.config = Config() - self.output = Output(__file__, self.config.Output) + self.output = Output(__file__) def test_deletion_in_frame(self): """ Simple in-frame deletion should give a simple description on protein level. """ - check_variant('AL449423.14(CDKN2A_v001):c.161_163del', - self.config, self.output) + check_variant('AL449423.14(CDKN2A_v001):c.161_163del', self.output) assert_equal(self.output.getIndexedOutput('genomicDescription', 0), 'AL449423.14:g.61937_61939del') assert 'AL449423.14(CDKN2A_v001):c.161_163del' \ @@ -42,8 +39,7 @@ class TestVariantchecker(): Simple in-frame insertion should give a simple description on protein level. """ - check_variant('AL449423.14(CDKN2A_v001):c.161_162insATC', - self.config, self.output) + check_variant('AL449423.14(CDKN2A_v001):c.161_162insATC', self.output) assert_equal(self.output.getIndexedOutput('genomicDescription', 0), 'AL449423.14:g.61938_61939insGAT') assert 'AL449423.14(CDKN2A_v001):c.161_162insATC' \ @@ -58,7 +54,7 @@ class TestVariantchecker(): protein level. """ check_variant('AL449423.14(CDKN2A_v001):c.161_162delinsATCCC', - self.config, self.output) + self.output) assert_equal(self.output.getIndexedOutput('genomicDescription', 0), 'AL449423.14:g.61938_61939delinsGGGAT') assert 'AL449423.14(CDKN2A_v001):c.161_162delinsATCCC' \ @@ -73,7 +69,7 @@ class TestVariantchecker(): protein level, also with the optional deleted sequence argument. """ check_variant('AL449423.14(CDKN2A_v001):c.161_162delTGinsATCCC', - self.config, self.output) + self.output) assert_equal(self.output.getIndexedOutput('genomicDescription', 0), 'AL449423.14:g.61938_61939delinsGGGAT') assert 'AL449423.14(CDKN2A_v001):c.161_162delinsATCCC' \ @@ -86,7 +82,7 @@ class TestVariantchecker(): """ Just a variant where we should roll. """ - check_variant('NM_003002.2:c.273del', self.config, self.output) + check_variant('NM_003002.2:c.273del', self.output) wroll = self.output.getMessagesWithErrorCode('WROLLFORWARD') assert len(wroll) > 0 @@ -94,7 +90,7 @@ class TestVariantchecker(): """ Just a variant where we cannot roll. """ - check_variant('NM_003002.2:c.274del', self.config, self.output) + check_variant('NM_003002.2:c.274del', self.output) wroll = self.output.getMessagesWithErrorCode('WROLLFORWARD') assert_equal(len(wroll), 0) @@ -102,7 +98,7 @@ class TestVariantchecker(): """ Here we can roll but should not, because it is over a splice site. """ - check_variant('NM_000088.3:g.459del', self.config, self.output) + check_variant('NM_000088.3:g.459del', self.output) wrollback = self.output.getMessagesWithErrorCode('IROLLBACK') assert len(wrollback) > 0 wroll = self.output.getMessagesWithErrorCode('WROLLFORWARD') @@ -113,7 +109,7 @@ class TestVariantchecker(): Here we can roll two positions, but should roll only one because otherwise it is over a splice site. """ - check_variant('NM_000088.3:g.494del', self.config, self.output) + check_variant('NM_000088.3:g.494del', self.output) wrollback = self.output.getMessagesWithErrorCode('IROLLBACK') assert len(wrollback) > 0 wroll = self.output.getMessagesWithErrorCode('WROLLFORWARD') @@ -123,7 +119,7 @@ class TestVariantchecker(): """ Here we can roll and should, we stay in the same exon. """ - check_variant('NM_000088.3:g.460del', self.config, self.output) + check_variant('NM_000088.3:g.460del', self.output) wroll = self.output.getMessagesWithErrorCode('WROLLFORWARD') assert len(wroll) > 0 @@ -155,7 +151,7 @@ class TestVariantchecker(): of AL449423.14:g.65471_65472insACT, where only the reverse roll should be done. """ - check_variant('AL449423.14:g.65470_65471insTAC', self.config, self.output) + check_variant('AL449423.14:g.65470_65471insTAC', self.output) assert 'AL449423.14(CDKN2A_v001):c.99_100insTAG' in self.output.getOutput('descriptions') assert_equal ('AL449423.14:g.65471_65472insACT', self.output.getIndexedOutput('genomicDescription', 0, '')) assert_equal(len(self.output.getMessagesWithErrorCode('WROLLFORWARD')), 1) @@ -165,7 +161,7 @@ class TestVariantchecker(): Insertion that rolls on the reverse strand should not use the same inserted sequence in descriptions on forward and reverse strands. """ - check_variant('AL449423.14:g.65471_65472insACT', self.config, self.output) + check_variant('AL449423.14:g.65471_65472insACT', self.output) assert 'AL449423.14(CDKN2A_v001):c.99_100insTAG' in self.output.getOutput('descriptions') assert_equal ('AL449423.14:g.65471_65472insACT', self.output.getIndexedOutput('genomicDescription', 0, '')) assert_equal(len(self.output.getMessagesWithErrorCode('WROLLFORWARD')), 0) @@ -175,7 +171,7 @@ class TestVariantchecker(): Roll warning message should only be shown for currently selected strand (forward). """ - check_variant('AL449423.14:g.65470_65471insTAC', self.config, self.output) + check_variant('AL449423.14:g.65470_65471insTAC', self.output) assert_equal(len(self.output.getMessagesWithErrorCode('WROLLFORWARD')), 1) assert_equal(len(self.output.getMessagesWithErrorCode('WROLLREVERSE')), 0) @@ -184,7 +180,7 @@ class TestVariantchecker(): Roll warning message should only be shown for currently selected strand (reverse). """ - check_variant('AL449423.14(CDKN2A_v001):c.98_99insGTA', self.config, self.output) + check_variant('AL449423.14(CDKN2A_v001):c.98_99insGTA', self.output) assert_equal(len(self.output.getMessagesWithErrorCode('WROLLFORWARD')), 0) assert_equal(len(self.output.getMessagesWithErrorCode('WROLLREVERSE')), 1) @@ -192,7 +188,7 @@ class TestVariantchecker(): """ Insertion on CDS start boundary should not be included in CDS. """ - check_variant('NM_000143.3:c.-1_1insCAT', self.config, self.output) + check_variant('NM_000143.3:c.-1_1insCAT', self.output) assert_equal(self.output.getIndexedOutput("newprotein", 0), None) # Todo: Is this a good test? @@ -200,7 +196,7 @@ class TestVariantchecker(): """ Insertion after CDS start boundary should be included in CDS. """ - check_variant('NM_000143.3:c.1_2insCAT', self.config, self.output) + check_variant('NM_000143.3:c.1_2insCAT', self.output) assert_equal(self.output.getIndexedOutput("newprotein", 0), '?') # Todo: Is this a good test? @@ -208,8 +204,7 @@ class TestVariantchecker(): """ Deletion hitting one splice site should not do a protein prediction. """ - check_variant('NG_012772.1(BRCA2_v001):c.632-5_670del', - self.config, self.output) + check_variant('NG_012772.1(BRCA2_v001):c.632-5_670del', self.output) assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0 assert_equal(self.output.getOutput('removedSpliceSites'), []) # Todo: For now, the following is how to check if no protein @@ -220,8 +215,7 @@ class TestVariantchecker(): """ Deletion of an entire exon should be possible. """ - check_variant('NG_012772.1(BRCA2_v001):c.632-5_681+7del', - self.config, self.output) + check_variant('NG_012772.1(BRCA2_v001):c.632-5_681+7del', self.output) assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0 assert_equal(self.output.getOutput('removedSpliceSites'), [2]) # Todo: For now, the following is how to check if protein @@ -232,8 +226,7 @@ class TestVariantchecker(): """ Deletion of exactly an exon should be possible. """ - check_variant('NG_012772.1(BRCA2_v001):c.632_681del', - self.config, self.output) + check_variant('NG_012772.1(BRCA2_v001):c.632_681del', self.output) assert_equal(len(self.output.getMessagesWithErrorCode('WOVERSPLICE')), 0) assert_equal(self.output.getOutput('removedSpliceSites'), [2]) # Todo: For now, the following is how to check if protein @@ -249,8 +242,7 @@ class TestVariantchecker(): NG_012772.1(BRCA2_v001):c.68-7_316+7del is such a variant, since positions 68 through 316 are exactly one exon and (316-68+1)/3 = 83. """ - check_variant('NG_012772.1(BRCA2_v001):c.68-7_316+7del', - self.config, self.output) + check_variant('NG_012772.1(BRCA2_v001):c.68-7_316+7del', self.output) assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0 assert_equal(self.output.getOutput('removedSpliceSites'), [2]) # Todo: For now, the following is how to check if protein @@ -262,8 +254,7 @@ class TestVariantchecker(): """ Deletion of two entire exons should be possible. """ - check_variant('NG_012772.1(BRCA2_v001):c.632-5_793+7del', - self.config, self.output) + check_variant('NG_012772.1(BRCA2_v001):c.632-5_793+7del', self.output) assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0 assert_equal(self.output.getOutput('removedSpliceSites'), [4]) # Todo: For now, the following is how to check if protein @@ -275,8 +266,7 @@ class TestVariantchecker(): Deletion of an entire intron should be possible (fusion of remaining exonic parts). """ - check_variant('NG_012772.1(BRCA2_v001):c.622_674del', - self.config, self.output) + check_variant('NG_012772.1(BRCA2_v001):c.622_674del', self.output) assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0 assert_equal(self.output.getOutput('removedSpliceSites'), [2]) # Todo: For now, the following is how to check if protein @@ -288,8 +278,7 @@ class TestVariantchecker(): Deletion of exactly an intron should be possible (fusion of flanking exons). """ - check_variant('NG_012772.1(BRCA2_v001):c.681+1_682-1del', - self.config, self.output) + check_variant('NG_012772.1(BRCA2_v001):c.681+1_682-1del', self.output) assert_equal(self.output.getMessagesWithErrorCode('WOVERSPLICE'), []) assert_equal(self.output.getOutput('removedSpliceSites'), [2]) # Note: The protein prediction is done, but 'newprotein' is not set @@ -304,8 +293,7 @@ class TestVariantchecker(): Deletion of an entire intron should be possible (fusion of remaining exonic parts). """ - check_variant('NG_012772.1(BRCA2_v001):c.622_672del', - self.config, self.output) + check_variant('NG_012772.1(BRCA2_v001):c.622_672del', self.output) assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0 assert_equal(self.output.getOutput('removedSpliceSites'), [2]) # Todo: For now, the following is how to check if protein @@ -317,8 +305,7 @@ class TestVariantchecker(): """ Deletion of an entire exon with unknown offsets should be possible. """ - check_variant('NG_012772.1(BRCA2_v001):c.632-?_681+?del', - self.config, self.output) + check_variant('NG_012772.1(BRCA2_v001):c.632-?_681+?del', self.output) assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0 assert len(self.output.getMessagesWithErrorCode('IDELSPLICE')) > 0 # Todo: For now, the following is how to check if protein @@ -343,8 +330,7 @@ class TestVariantchecker(): NG_012772.1(BRCA2_v001):c.68-?_316+?del is such a variant, since positions 68 through 316 are exactly one exon and (316-68+1)/3 = 83. """ - check_variant('NG_012772.1(BRCA2_v001):c.68-?_316+?del', - self.config, self.output) + check_variant('NG_012772.1(BRCA2_v001):c.68-?_316+?del', self.output) assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0 assert len(self.output.getMessagesWithErrorCode('IDELSPLICE')) > 0 # Todo: For now, the following is how to check if protein @@ -364,7 +350,7 @@ class TestVariantchecker(): variant with exact positioning should be possible. """ check_variant('NG_012772.1(BRCA2_v001):c.[632-?_681+?del;681+4del]', - self.config, self.output) + self.output) assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0 assert len(self.output.getMessagesWithErrorCode('IDELSPLICE')) > 0 # Todo: For now, the following is how to check if protein @@ -384,7 +370,7 @@ class TestVariantchecker(): also on the reverse strand. """ check_variant('AL449423.14(CDKN2A_v001):c.151-?_457+?del', - self.config, self.output) + self.output) assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0 assert len(self.output.getMessagesWithErrorCode('IDELSPLICE')) > 0 # Todo: For now, the following is how to check if protein @@ -405,7 +391,7 @@ class TestVariantchecker(): of the flanking exons (as would happen using the mechanism for genomic references). """ - check_variant('NM_018723.3:c.758_890del', self.config, self.output) + check_variant('NM_018723.3:c.758_890del', self.output) assert_equal(len(self.output.getMessagesWithErrorCode('WOVERSPLICE')), 0) assert_equal(self.output.getOutput('removedSpliceSites'), [2]) # Todo: For now, the following is how to check if protein @@ -416,12 +402,12 @@ class TestVariantchecker(): """ Insertion of a range is not implemented yet. """ - check_variant('AB026906.1:c.274_275ins262_268', self.config, self.output) + check_variant('AB026906.1:c.274_275ins262_268', self.output) assert_equal(len(self.output.getMessagesWithErrorCode('ENOTIMPLEMENTED')), 1) def test_delins_range(self): """ Deletion/insertion of a range is not implemented yet. """ - check_variant('AB026906.1:c.274delins262_268', self.config, self.output) + check_variant('AB026906.1:c.274delins262_268', self.output) assert_equal(len(self.output.getMessagesWithErrorCode('ENOTIMPLEMENTED')), 1) diff --git a/tests/test_webservice.py b/tests/test_webservice.py index 5c7437843943c9473338402ce4db0825391a091c..3e5f99d996d9bcee0e845ba45e6451e0c7dada15 100644 --- a/tests/test_webservice.py +++ b/tests/test_webservice.py @@ -8,7 +8,6 @@ from mutalyzer.util import monkey_patch_suds; monkey_patch_suds() import os from datetime import datetime, timedelta import mutalyzer -from mutalyzer.config import Config from mutalyzer.output import Output from mutalyzer.sync import CacheSync from mutalyzer import Db @@ -226,10 +225,9 @@ class TestWebservice(): """ created_since = datetime.today() - timedelta(days=14) - config = Config() - database = Db.Cache(config.Db) - output = Output(__file__, config.Output) - sync = CacheSync(config.Retriever, output, database) + database = Db.Cache() + output = Output(__file__) + sync = CacheSync(output, database) cache = sync.local_cache(created_since) r = self.client.service.getCache(created_since)