From 1a09c50686a5b3e030815f82200a30557b1b4c5d Mon Sep 17 00:00:00 2001 From: Martijn Vermaat <martijn@vermaat.name> Date: Wed, 23 May 2012 14:32:13 +0000 Subject: [PATCH] Port from soaplib to current rpclib git-svn-id: https://humgenprojects.lumc.nl/svn/mutalyzer/branches/rpclib-branch@534 eb6bd6ab-9ccd-42b9-aceb-e2899b4a52f1 --- mutalyzer/models.py | 38 +++--- mutalyzer/webservice.py | 292 ++++++++++++++++++++-------------------- mutalyzer/website.py | 5 +- 3 files changed, 172 insertions(+), 163 deletions(-) diff --git a/mutalyzer/models.py b/mutalyzer/models.py index 41c3afd8..0dcc07ec 100644 --- a/mutalyzer/models.py +++ b/mutalyzer/models.py @@ -1,13 +1,13 @@ """ Collection of serilizable objects used by the SOAP webservice. They extend -from the soaplib ClassModel. +from the rpclib ClassModel. -Default attributes for the soaplib ClassModel: +Default attributes for the rpclib ClassModel: - nillable = True - min_occurs = 0 - max_occurs = 1 -Additional attributes values for the soaplib String model: +Additional attributes values for the rpclib String model: - min_len = 0 - max_len = 'unbounded' - pattern = None @@ -17,15 +17,15 @@ Additional attributes values for the soaplib String model: """ -from soaplib.core.model.primitive import String, Integer, Boolean, DateTime -from soaplib.core.model.clazz import ClassModel, Array +from rpclib.model.primitive import String, Integer, Boolean, DateTime +from rpclib.model.complex import ComplexModel, Array from mutalyzer import SOAP_NAMESPACE class Mandatory(object): """ - This is soaplib.model.primitive.Mandatory, but without min_length=1 for + This is rpclib.model.primitive.Mandatory, but without min_length=1 for the String model. """ String = String(min_occurs=1, nillable=False) @@ -35,7 +35,7 @@ class Mandatory(object): #Mandatory -class SoapMessage(ClassModel): +class SoapMessage(ComplexModel): """ Type of messages used in SOAP method return values. """ @@ -46,7 +46,7 @@ class SoapMessage(ClassModel): #SoapMessage -class Mapping(ClassModel): +class Mapping(ComplexModel): """ Return type of SOAP method mappingInfo. """ @@ -64,7 +64,7 @@ class Mapping(ClassModel): #Mapping -class Transcript(ClassModel): +class Transcript(ComplexModel): """ Return type of SOAP method transcriptInfo. """ @@ -76,7 +76,7 @@ class Transcript(ClassModel): #Transcript -class RawVariant(ClassModel): +class RawVariant(ComplexModel): """ Used in MutalyzerOutput data type. """ @@ -87,7 +87,7 @@ class RawVariant(ClassModel): #RawVariant -class MutalyzerOutput(ClassModel): +class MutalyzerOutput(ComplexModel): """ Return type of SOAP method runMutalyzer. """ @@ -128,7 +128,7 @@ class MutalyzerOutput(ClassModel): #MutalyzerOutput -class TranscriptNameInfo(ClassModel): +class TranscriptNameInfo(ComplexModel): """ Return type of SOAP method getGeneAndTranscript. """ @@ -139,7 +139,7 @@ class TranscriptNameInfo(ClassModel): #TranscriptNameInfo -class ExonInfo(ClassModel): +class ExonInfo(ComplexModel): """ Used in TranscriptInfo data type. """ @@ -154,7 +154,7 @@ class ExonInfo(ClassModel): #ExonInfo -class ProteinTranscript(ClassModel): +class ProteinTranscript(ComplexModel): """ Used in TranscriptInfo data type. """ @@ -166,7 +166,7 @@ class ProteinTranscript(ClassModel): #ProteinTranscript -class TranscriptInfo(ClassModel): +class TranscriptInfo(ComplexModel): """ Used in return type of SOAP method getTranscriptsAndInfo. @@ -206,7 +206,7 @@ class TranscriptInfo(ClassModel): #TranscriptInfo -class TranscriptMappingInfo(ClassModel): +class TranscriptMappingInfo(ComplexModel): """ Used in return type of SOAP method getTranscriptsRange. """ @@ -226,7 +226,7 @@ class TranscriptMappingInfo(ClassModel): #TranscriptMappingInfo -class CheckSyntaxOutput(ClassModel): +class CheckSyntaxOutput(ComplexModel): """ Return type of SOAP method checkSyntax. """ @@ -237,7 +237,7 @@ class CheckSyntaxOutput(ClassModel): #CheckSyntaxOutput -class InfoOutput(ClassModel): +class InfoOutput(ComplexModel): """ Return type of SOAP method info. """ @@ -253,7 +253,7 @@ class InfoOutput(ClassModel): #InfoOutput -class CacheEntry(ClassModel): +class CacheEntry(ComplexModel): """ Used in getCache SOAP method. """ diff --git a/mutalyzer/webservice.py b/mutalyzer/webservice.py index 71c3447b..826a0ce1 100644 --- a/mutalyzer/webservice.py +++ b/mutalyzer/webservice.py @@ -20,13 +20,14 @@ sys.stdout = sys.stderr # Log exceptions to stdout import logging; logging.basicConfig() -from soaplib.core import Application -from soaplib.core.service import soap -from soaplib.core.service import DefinitionBase -from soaplib.core.model.primitive import String, Integer, Boolean, DateTime -from soaplib.core.model.clazz import Array -from soaplib.core.model.exception import Fault -from soaplib.core.server import wsgi +from rpclib.application import Application +from rpclib.protocol.soap import Soap11 +from rpclib.decorator import srpc +from rpclib.service import ServiceBase +from rpclib.model.primitive import String, Integer, Boolean, DateTime +from rpclib.model.complex import Array +from rpclib.model.fault import Fault +from rpclib.server.wsgi import WsgiApplication import os import socket from operator import itemgetter, attrgetter @@ -44,102 +45,106 @@ from mutalyzer import GenRecord from mutalyzer.models import * -class MutalyzerService(DefinitionBase): +def _checkBuild(L, build) : """ - Mutalyzer webservices. + Check if the build is supported (hg18 or hg19). - These methods are made public via a SOAP interface. + Returns: + - Nothing (but raises an EARG exception). + + @arg L: An output object for logging. + @type L: object + @arg build: The human genome build name that needs to be checked. + @type build: string """ - def __init__(self, environ=None): - super(MutalyzerService, self).__init__(environ) - #__init__ - def __checkBuild(self, L, build) : - """ - Check if the build is supported (hg18 or hg19). + 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 " \ + "build name." % build) + #if +#_checkBuild - Returns: - - Nothing (but raises an EARG exception). - @arg L: An output object for logging. - @type L: object - @arg build: The human genome build name that needs to be checked. - @type build: string - """ +def _checkChrom(L, D, chrom) : + """ + Check if the chromosome is in our database. - 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 " \ - "build name." % build) - #if - #__checkBuild + Returns: + - Nothing (but raises an EARG exception). - def __checkChrom(self, L, D, chrom) : - """ - Check if the chromosome is in our database. + @arg L: An output object for logging. + @type L: object + @arg D: A handle to the database. + @type D: object + @arg chrom: The name of the chromosome. + @type chrom: string + """ - Returns: - - Nothing (but raises an EARG exception). + if not D.isChrom(chrom) : + L.addMessage(__file__, 4, "EARG", "EARG %s" % chrom) + raise Fault("EARG", + "The chrom argument (%s) was not a valid " \ + "chromosome name." % chrom) + #if +#_checkChrom - @arg L: An output object for logging. - @type L: object - @arg D: A handle to the database. - @type D: object - @arg chrom: The name of the chromosome. - @type chrom: string - """ - if not D.isChrom(chrom) : - L.addMessage(__file__, 4, "EARG", "EARG %s" % chrom) - raise Fault("EARG", - "The chrom argument (%s) was not a valid " \ - "chromosome name." % chrom) - #if - #__checkChrom +def _checkPos(L, pos) : + """ + Check if the position is valid. + + Returns: + - Nothing (but raises an ERANGE exception). - def __checkPos(self, L, pos) : - """ - Check if the position is valid. + @arg L: An output object for logging. + @type L: object + @arg pos: The position. + @type pos: integer + """ - Returns: - - Nothing (but raises an ERANGE exception). + if pos < 1 : + L.addMessage(__file__, 4, "ERANGE", "ERANGE %i" % pos) + raise Fault("ERANGE", + "The pos argument (%i) is out of range." % pos) + #if +#_checkPos - @arg L: An output object for logging. - @type L: object - @arg pos: The position. - @type pos: integer - """ - if pos < 1 : - L.addMessage(__file__, 4, "ERANGE", "ERANGE %i" % pos) - raise Fault("ERANGE", - "The pos argument (%i) is out of range." % pos) - #if - #__checkPos +def _checkVariant(L, variant) : + """ + Check if a variant is provided. - def __checkVariant(self, L, variant) : - """ - Check if a variant is provided. + Returns: + - Nothing (but raises an EARG exception). - Returns: - - Nothing (but raises an EARG exception). + @arg L: An output object for logging. + @type L: object + @arg variant: The variant. + @type variant: string + """ + + if not variant : + L.addMessage(__file__, 4, "EARG", "EARG no variant") + raise Fault("EARG", "The variant argument is not provided.") + #if +#_checkVariant - @arg L: An output object for logging. - @type L: object - @arg variant: The variant. - @type variant: string - """ - if not variant : - L.addMessage(__file__, 4, "EARG", "EARG no variant") - raise Fault("EARG", "The variant argument is not provided.") - #if - #__checkVariant +class MutalyzerService(ServiceBase): + """ + Mutalyzer webservices. + + These methods are made public via a SOAP interface. + """ + def __init__(self, environ=None): + super(MutalyzerService, self).__init__(environ) + #__init__ - @soap(Mandatory.String, Mandatory.String, Mandatory.Integer, Boolean, + @srpc(Mandatory.String, Mandatory.String, Mandatory.Integer, Boolean, _returns = Array(Mandatory.String)) - def getTranscripts(self, build, chrom, pos, versions=False) : + def getTranscripts(build, chrom, pos, versions=False) : """ Get all the transcripts that overlap with a chromosomal position. @@ -167,11 +172,11 @@ class MutalyzerService(DefinitionBase): "Received request getTranscripts(%s %s %s %s)" % (build, chrom, pos, versions)) - self.__checkBuild(L, build) + _checkBuild(L, build) D = Db.Mapping(build) - self.__checkChrom(L, D, chrom) - self.__checkPos(L, pos) + _checkChrom(L, D, chrom) + _checkPos(L, pos) ret = D.get_Transcripts(chrom, pos, pos, True) @@ -192,8 +197,8 @@ class MutalyzerService(DefinitionBase): return ret #getTranscripts - @soap(Mandatory.String, Mandatory.String, _returns = Array(Mandatory.String)) - def getTranscriptsByGeneName(self, build, name): + @srpc(Mandatory.String, Mandatory.String, _returns = Array(Mandatory.String)) + def getTranscriptsByGeneName(build, name): """ Todo: documentation. """ @@ -203,7 +208,7 @@ class MutalyzerService(DefinitionBase): "Received request getTranscriptsByGene(%s %s)" % (build, name)) - self.__checkBuild(L, build) + _checkBuild(L, build) D = Db.Mapping(build) ret = D.get_TranscriptsByGeneName(name) @@ -221,9 +226,9 @@ class MutalyzerService(DefinitionBase): return [] #getTranscriptsByGene - @soap(Mandatory.String, Mandatory.String, Mandatory.Integer, + @srpc(Mandatory.String, Mandatory.String, Mandatory.Integer, Mandatory.Integer, Mandatory.Integer, _returns = Array(Mandatory.String)) - def getTranscriptsRange(self, build, chrom, pos1, pos2, method) : + def getTranscriptsRange(build, chrom, pos1, pos2, method) : """ Get all the transcripts that overlap with a range on a chromosome. @@ -250,7 +255,7 @@ class MutalyzerService(DefinitionBase): chrom, pos1, pos2, method)) D = Db.Mapping(build) - self.__checkBuild(L, build) + _checkBuild(L, build) ret = D.get_Transcripts(chrom, pos1, pos2, method) @@ -265,9 +270,9 @@ class MutalyzerService(DefinitionBase): return ret #getTranscriptsRange - @soap(Mandatory.String, Mandatory.String, Mandatory.Integer, + @srpc(Mandatory.String, Mandatory.String, Mandatory.Integer, Mandatory.Integer, Mandatory.Integer, _returns = Array(TranscriptMappingInfo)) - def getTranscriptsMapping(self, build, chrom, pos1, pos2, method): + def getTranscriptsMapping(build, chrom, pos1, pos2, method): """ Get all the transcripts and their info that overlap with a range on a chromosome. @@ -301,7 +306,7 @@ class MutalyzerService(DefinitionBase): 'getTranscriptsRange(%s %s %s %s %s)' % \ (build, chrom, pos1, pos2, method)) - self.__checkBuild(output, build) + _checkBuild(output, build) database = Db.Mapping(build) transcripts = [] @@ -332,8 +337,8 @@ class MutalyzerService(DefinitionBase): return transcripts #getTranscriptsMapping - @soap(Mandatory.String, Mandatory.String, _returns = Mandatory.String) - def getGeneName(self, build, accno) : + @srpc(Mandatory.String, Mandatory.String, _returns = Mandatory.String) + def getGeneName(build, accno) : """ Find the gene name associated with a transcript. @@ -351,7 +356,7 @@ class MutalyzerService(DefinitionBase): "Received request getGeneName(%s %s)" % (build, accno)) D = Db.Mapping(build) - self.__checkBuild(L, build) + _checkBuild(L, build) ret = D.get_GeneName(accno.split('.')[0]) @@ -363,9 +368,9 @@ class MutalyzerService(DefinitionBase): #getGeneName - @soap(Mandatory.String, Mandatory.String, Mandatory.String, + @srpc(Mandatory.String, Mandatory.String, Mandatory.String, Mandatory.String, _returns = Mapping) - def mappingInfo(self, LOVD_ver, build, accNo, variant) : + def mappingInfo(LOVD_ver, build, accNo, variant) : """ Search for an NM number in the MySQL database, if the version number matches, get the start and end positions in a variant and @@ -421,9 +426,9 @@ class MutalyzerService(DefinitionBase): return result #mappingInfo - @soap(Mandatory.String, Mandatory.String, Mandatory.String, + @srpc(Mandatory.String, Mandatory.String, Mandatory.String, _returns = Transcript) - def transcriptInfo(self, LOVD_ver, build, accNo) : + def transcriptInfo(LOVD_ver, build, accNo) : """ Search for an NM number in the MySQL database, if the version number matches, the transcription start and end and CDS end @@ -457,8 +462,8 @@ class MutalyzerService(DefinitionBase): return T #transcriptInfo - @soap(Mandatory.String, Mandatory.String, _returns = Mandatory.String) - def chromAccession(self, build, name) : + @srpc(Mandatory.String, Mandatory.String, _returns = Mandatory.String) + def chromAccession(build, name) : """ Get the accession number of a chromosome, given a name. @@ -476,8 +481,8 @@ class MutalyzerService(DefinitionBase): L.addMessage(__file__, -1, "INFO", "Received request chromAccession(%s %s)" % (build, name)) - self.__checkBuild(L, build) - self.__checkChrom(L, D, name) + _checkBuild(L, build) + _checkChrom(L, D, name) result = D.chromAcc(name) @@ -489,8 +494,8 @@ class MutalyzerService(DefinitionBase): return result #chromAccession - @soap(Mandatory.String, Mandatory.String, _returns = Mandatory.String) - def chromosomeName(self, build, accNo) : + @srpc(Mandatory.String, Mandatory.String, _returns = Mandatory.String) + def chromosomeName(build, accNo) : """ Get the name of a chromosome, given a chromosome accession number. @@ -508,8 +513,8 @@ class MutalyzerService(DefinitionBase): L.addMessage(__file__, -1, "INFO", "Received request chromName(%s %s)" % (build, accNo)) - self.__checkBuild(L, build) -# self.__checkChrom(L, D, name) + _checkBuild(L, build) +# self._checkChrom(L, D, name) result = D.chromName(accNo) @@ -521,8 +526,8 @@ class MutalyzerService(DefinitionBase): return result #chromosomeName - @soap(Mandatory.String, Mandatory.String, _returns = Mandatory.String) - def getchromName(self, build, acc) : + @srpc(Mandatory.String, Mandatory.String, _returns = Mandatory.String) + def getchromName(build, acc) : """ Get the chromosome name, given a transcript identifier (NM number). @@ -540,8 +545,8 @@ class MutalyzerService(DefinitionBase): L.addMessage(__file__, -1, "INFO", "Received request getchromName(%s %s)" % (build, acc)) - self.__checkBuild(L, build) -# self.__checkChrom(L, D, name) + _checkBuild(L, build) +# self._checkChrom(L, D, name) result = D.get_chromName(acc) @@ -553,8 +558,8 @@ class MutalyzerService(DefinitionBase): return result #chromosomeName - @soap(Mandatory.String, Mandatory.String, String, _returns = Array(Mandatory.String)) - def numberConversion(self, build, variant, gene=None): + @srpc(Mandatory.String, Mandatory.String, String, _returns = Array(Mandatory.String)) + def numberConversion(build, variant, gene=None): """ Converts I{c.} to I{g.} notation or vice versa @@ -591,8 +596,8 @@ class MutalyzerService(DefinitionBase): return result #numberConversion - @soap(Mandatory.String, _returns = CheckSyntaxOutput) - def checkSyntax(self, variant): + @srpc(Mandatory.String, _returns = CheckSyntaxOutput) + def checkSyntax(variant): """ Checks the syntax of a variant. @@ -611,7 +616,7 @@ class MutalyzerService(DefinitionBase): result = CheckSyntaxOutput() - self.__checkVariant(output, variant) + _checkVariant(output, variant) grammar = Grammar(output) parsetree = grammar.parse(variant) @@ -630,8 +635,8 @@ class MutalyzerService(DefinitionBase): return result #checkSyntax - @soap(Mandatory.String, _returns = MutalyzerOutput) - def runMutalyzer(self, variant) : + @srpc(Mandatory.String, _returns = MutalyzerOutput) + def runMutalyzer(variant) : """ Run the Mutalyzer name checker. @@ -687,7 +692,7 @@ class MutalyzerService(DefinitionBase): result.molecule = O.getIndexedOutput('molecule', 0) # We force the results to strings here, because some results - # may be of type Bio.Seq.Seq which soaplib doesn't like. + # may be of type Bio.Seq.Seq which rpclib doesn't like. # # todo: We might have to also do this elsewhere. @@ -735,8 +740,8 @@ class MutalyzerService(DefinitionBase): return result #runMutalyzer - @soap(Mandatory.String, Mandatory.String, _returns = TranscriptNameInfo) - def getGeneAndTranscript(self, genomicReference, transcriptReference) : + @srpc(Mandatory.String, Mandatory.String, _returns = TranscriptNameInfo) + def getGeneAndTranscript(genomicReference, transcriptReference) : """ Todo: documentation. """ @@ -768,8 +773,8 @@ class MutalyzerService(DefinitionBase): return ret #getGeneAndTranscript - @soap(Mandatory.String, String, _returns = Array(TranscriptInfo)) - def getTranscriptsAndInfo(self, genomicReference, geneName=None): + @srpc(Mandatory.String, String, _returns = Array(TranscriptInfo)) + def getTranscriptsAndInfo(genomicReference, geneName=None): """ Given a genomic reference, return all its transcripts with their transcription/cds start/end sites and exons. @@ -909,25 +914,25 @@ class MutalyzerService(DefinitionBase): return transcripts #getTranscriptsAndInfo - @soap(Mandatory.String, _returns = Mandatory.String) - def upLoadGenBankLocalFile(self, content) : + @srpc(Mandatory.String, _returns = Mandatory.String) + def upLoadGenBankLocalFile(content) : """ Not implemented yet. """ raise Fault('ENOTIMPLEMENTED', 'Not implemented yet') #upLoadGenBankLocalFile - @soap(Mandatory.String, _returns = Mandatory.String) - def upLoadGenBankRemoteFile(self, url) : + @srpc(Mandatory.String, _returns = Mandatory.String) + def upLoadGenBankRemoteFile(url) : """ Not implemented yet. """ raise Fault('ENOTIMPLEMENTED', 'Not implemented yet') #upLoadGenBankRemoteFile - @soap(Mandatory.String, Mandatory.String, Mandatory.Integer, + @srpc(Mandatory.String, Mandatory.String, Mandatory.Integer, Mandatory.Integer, _returns = Mandatory.String) - def sliceChromosomeByGene(self, geneSymbol, organism, upStream, + def sliceChromosomeByGene(geneSymbol, organism, upStream, downStream) : """ Todo: documentation, error handling, argument checking, tests. @@ -955,9 +960,9 @@ class MutalyzerService(DefinitionBase): return UD #sliceChromosomeByGene - @soap(Mandatory.String, Mandatory.Integer, Mandatory.Integer, + @srpc(Mandatory.String, Mandatory.Integer, Mandatory.Integer, Mandatory.Integer, _returns = Mandatory.String) - def sliceChromosome(self, chromAccNo, start, end, orientation) : + def sliceChromosome(chromAccNo, start, end, orientation) : """ Todo: documentation, error handling, argument checking, tests. @@ -982,8 +987,8 @@ class MutalyzerService(DefinitionBase): return UD #sliceChromosome - @soap(_returns = InfoOutput) - def info(self): + @srpc(_returns = InfoOutput) + def info(): """ Gives some static application information, such as the current running version. @@ -1020,8 +1025,8 @@ class MutalyzerService(DefinitionBase): return result #info - @soap(_returns = Mandatory.String) - def ping(self): + @srpc(_returns = Mandatory.String) + def ping(): """ Simple function to test the interface. @@ -1031,8 +1036,8 @@ class MutalyzerService(DefinitionBase): return 'pong' #ping - @soap(DateTime, _returns = Array(CacheEntry)) - def getCache(self, created_since=None): + @srpc(DateTime, _returns = Array(CacheEntry)) + def getCache(created_since=None): """ Get a list of entries from the local cache created since given date. @@ -1063,8 +1068,8 @@ class MutalyzerService(DefinitionBase): return map(cache_entry_to_soap, cache) #getCache - @soap(Mandatory.String, _returns = Array(Mandatory.String)) - def getdbSNPDescriptions(self, rs_id): + @srpc(Mandatory.String, _returns = Array(Mandatory.String)) + def getdbSNPDescriptions(rs_id): """ Lookup HGVS descriptions for a dbSNP rs identifier. @@ -1099,9 +1104,10 @@ class MutalyzerService(DefinitionBase): # WSGI application for use with e.g. Apache/mod_wsgi soap_application = Application([MutalyzerService], mutalyzer.SOAP_NAMESPACE, - 'Mutalyzer') + in_protocol=Soap11(), out_protocol=Soap11(), + name='Mutalyzer') # Note: We would like to create the wsgi.Application instance only in the # bin/mutalyzer-webservice.wsgi script, but unfortunately this breaks the # get_wsdl method of soap_application which we use to generate API # documentation in website.py. -application = wsgi.Application(soap_application) +application = WsgiApplication(soap_application) diff --git a/mutalyzer/website.py b/mutalyzer/website.py index 2c956243..67245a8f 100644 --- a/mutalyzer/website.py +++ b/mutalyzer/website.py @@ -28,6 +28,7 @@ from lxml import etree from cStringIO import StringIO from simpletal import simpleTALES from simpletal import simpleTAL +from rpclib.interface.wsdl import Wsdl11 import mutalyzer from mutalyzer import util @@ -1443,7 +1444,9 @@ class Documentation: @todo: Cache this transformation. """ url = web.ctx.homedomain + web.ctx.homepath + WEBSERVICE_LOCATION - wsdl_handle = StringIO(webservice.soap_application.get_wsdl(url)) + wsdl = Wsdl11(webservice.soap_application.interface) + wsdl.build_interface_document(url) + wsdl_handle = StringIO(wsdl.get_interface_document()) xsl_handle = open(os.path.join(mutalyzer.package_root(), WSDL_VIEWER), 'r') wsdl_doc = etree.parse(wsdl_handle) -- GitLab