From 0e1c2d92eb39468bfcdb1146b98a14bbc7295482 Mon Sep 17 00:00:00 2001 From: Martijn Vermaat <martijn@vermaat.name> Date: Sat, 27 Sep 2014 10:35:20 +0200 Subject: [PATCH] Use unicode string arguments in webservice interface definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes Spyne to not crash on POST requests to the HTTP/RPC+JSON webservice. Note that all return values still use byte strings. Changing those will touch a larger part of the codebase, and will be done in another commit. As per [1]: > Unlike the Python str, the Spyne String is not for arbitrary byte > streams. You should not use it unless you are absolutely, positively > sure that you need to deal with text data with an unknown encoding. In > all other cases, you should just use the Unicode type. They actually > look the same from outside, this distinction is made just to properly > deal with the quirks surrounding Python-2’s unicode type. > > Remember that you have the ByteArray and File types at your disposal > when you need to deal with arbitrary byte streams. > > The String type will be just an alias for Unicode once Spyne gets > ported to Python 3. It might even be deprecated and removed in the > future, so make sure you are using either Unicode or ByteArray in your > interface definitions. [1] http://spyne.io/docs/2.10/manual/03_types.html#strings --- mutalyzer/models.py | 3 ++- mutalyzer/services/rpc.py | 50 +++++++++++++++++++-------------------- requirements.txt | 2 +- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/mutalyzer/models.py b/mutalyzer/models.py index f7356dda..387314ca 100644 --- a/mutalyzer/models.py +++ b/mutalyzer/models.py @@ -20,7 +20,7 @@ Additional attributes values for the spyne String model: """ -from spyne.model.primitive import String, Integer, Boolean, DateTime +from spyne.model.primitive import String, Integer, Boolean, DateTime, Unicode from spyne.model.binary import ByteArray from spyne.model.complex import ComplexModel, Array @@ -33,6 +33,7 @@ class Mandatory(object): the String model. """ String = String(type_name='mandatory_string', min_occurs=1, nillable=False) + Unicode = Unicode(type_name='mandatory_unicode', min_occurs=1, nillable=False) Integer = Integer(type_name='mandatory_integer', min_occurs=1, nillable=False) Boolean = Boolean(type_name='mandatory_boolean', min_occurs=1, nillable=False) DateTime = DateTime(type_name='mandatory_date_time', min_occurs=1, nillable=False) diff --git a/mutalyzer/services/rpc.py b/mutalyzer/services/rpc.py index d681b94c..9ad68b94 100644 --- a/mutalyzer/services/rpc.py +++ b/mutalyzer/services/rpc.py @@ -11,7 +11,7 @@ Mutalyzer RPC services. from spyne.decorator import srpc from spyne.service import ServiceBase -from spyne.model.primitive import String, Integer, Boolean, DateTime +from spyne.model.primitive import String, Integer, Boolean, DateTime, Unicode from spyne.model.complex import Array from spyne.model.fault import Fault import os @@ -51,7 +51,7 @@ class MutalyzerService(ServiceBase): super(MutalyzerService, self).__init__(environ) #__init__ - @srpc(Mandatory.ByteArray, String, String, _returns=String) + @srpc(Mandatory.ByteArray, Unicode, Unicode, _returns=String) def submitBatchJob(data, process='NameChecker', argument=''): """ Submit a batch job. @@ -115,7 +115,7 @@ class MutalyzerService(ServiceBase): batch_types[process], argument) return result_id - @srpc(Mandatory.String, _returns=Integer) + @srpc(Mandatory.Unicode, _returns=Integer) def monitorBatchJob(job_id): """ Get the number of entries left for a batch job. @@ -129,7 +129,7 @@ class MutalyzerService(ServiceBase): """ return BatchQueueItem.query.join(BatchJob).filter_by(result_id=job_id).count() - @srpc(Mandatory.String, _returns=ByteArray) + @srpc(Mandatory.Unicode, _returns=ByteArray) def getBatchJob(job_id): """ Get the result of a batch job. @@ -155,7 +155,7 @@ class MutalyzerService(ServiceBase): handle = open(os.path.join(settings.CACHE_DIR, filename)) return handle - @srpc(Mandatory.String, Mandatory.String, Mandatory.Integer, Boolean, + @srpc(Mandatory.Unicode, Mandatory.Unicode, Mandatory.Integer, Boolean, _returns=Array(Mandatory.String)) def getTranscripts(build, chrom, pos, versions=False) : """ @@ -215,7 +215,7 @@ class MutalyzerService(ServiceBase): return [m.accession for m in mappings] #getTranscripts - @srpc(Mandatory.String, Mandatory.String, _returns=Array(Mandatory.String)) + @srpc(Mandatory.Unicode, Mandatory.Unicode, _returns=Array(Mandatory.String)) def getTranscriptsByGeneName(build, name): """ Todo: documentation. @@ -243,7 +243,7 @@ class MutalyzerService(ServiceBase): return ['%s.%s' % (m.accession, m.version) for m in mappings] #getTranscriptsByGene - @srpc(Mandatory.String, Mandatory.String, Mandatory.Integer, + @srpc(Mandatory.Unicode, Mandatory.Unicode, Mandatory.Integer, Mandatory.Integer, Mandatory.Integer, _returns=Array(Mandatory.String)) def getTranscriptsRange(build, chrom, pos1, pos2, method) : """ @@ -302,7 +302,7 @@ class MutalyzerService(ServiceBase): return [m.accession for m in mappings] #getTranscriptsRange - @srpc(Mandatory.String, Mandatory.String, Mandatory.Integer, + @srpc(Mandatory.Unicode, Mandatory.Unicode, Mandatory.Integer, Mandatory.Integer, Mandatory.Integer, _returns=Array(TranscriptMappingInfo)) def getTranscriptsMapping(build, chrom, pos1, pos2, method): @@ -387,7 +387,7 @@ class MutalyzerService(ServiceBase): return transcripts #getTranscriptsMapping - @srpc(Mandatory.String, Mandatory.String, _returns=Mandatory.String) + @srpc(Mandatory.Unicode, Mandatory.Unicode, _returns=Mandatory.String) def getGeneName(build, accno) : """ Find the gene name associated with a transcript. @@ -424,8 +424,8 @@ class MutalyzerService(ServiceBase): return mapping.gene #getGeneName - @srpc(Mandatory.String, Mandatory.String, Mandatory.String, - Mandatory.String, _returns=Mapping) + @srpc(Mandatory.Unicode, Mandatory.Unicode, Mandatory.Unicode, + Mandatory.Unicode, _returns=Mapping) def mappingInfo(LOVD_ver, build, accNo, variant) : """ Search for an NM number in the MySQL database, if the version @@ -492,7 +492,7 @@ class MutalyzerService(ServiceBase): return result #mappingInfo - @srpc(Mandatory.String, Mandatory.String, Mandatory.String, + @srpc(Mandatory.Unicode, Mandatory.Unicode, Mandatory.Unicode, _returns=Transcript) def transcriptInfo(LOVD_ver, build, accNo) : """ @@ -536,7 +536,7 @@ class MutalyzerService(ServiceBase): return T #transcriptInfo - @srpc(Mandatory.String, Mandatory.String, _returns=Mandatory.String) + @srpc(Mandatory.Unicode, Mandatory.Unicode, _returns=Mandatory.String) def chromAccession(build, name) : """ Get the accession number of a chromosome, given a name. @@ -574,7 +574,7 @@ class MutalyzerService(ServiceBase): return chromosome.accession #chromAccession - @srpc(Mandatory.String, Mandatory.String, _returns=Mandatory.String) + @srpc(Mandatory.Unicode, Mandatory.Unicode, _returns=Mandatory.String) def chromosomeName(build, accNo) : """ Get the name of a chromosome, given a chromosome accession number. @@ -612,7 +612,7 @@ class MutalyzerService(ServiceBase): return chromosome.name #chromosomeName - @srpc(Mandatory.String, Mandatory.String, _returns=Mandatory.String) + @srpc(Mandatory.Unicode, Mandatory.Unicode, _returns=Mandatory.String) def getchromName(build, acc) : """ Get the chromosome name, given a transcript identifier (NM number). @@ -649,7 +649,7 @@ class MutalyzerService(ServiceBase): return mapping.chromosome.name #chromosomeName - @srpc(Mandatory.String, Mandatory.String, String, + @srpc(Mandatory.Unicode, Mandatory.Unicode, Unicode, _returns=Array(Mandatory.String)) def numberConversion(build, variant, gene=None): """ @@ -696,7 +696,7 @@ class MutalyzerService(ServiceBase): return result #numberConversion - @srpc(Mandatory.String, _returns=CheckSyntaxOutput) + @srpc(Mandatory.Unicode, _returns=CheckSyntaxOutput) def checkSyntax(variant): """ Checks the syntax of a variant. @@ -739,7 +739,7 @@ class MutalyzerService(ServiceBase): return result #checkSyntax - @srpc(Mandatory.String, _returns=MutalyzerOutput) + @srpc(Mandatory.Unicode, _returns=MutalyzerOutput) def runMutalyzer(variant) : """ Run the Mutalyzer name checker. @@ -860,7 +860,7 @@ class MutalyzerService(ServiceBase): return result #runMutalyzer - @srpc(Mandatory.String, Mandatory.String, _returns=TranscriptNameInfo) + @srpc(Mandatory.Unicode, Mandatory.Unicode, _returns=TranscriptNameInfo) def getGeneAndTranscript(genomicReference, transcriptReference) : """ Todo: documentation. @@ -892,7 +892,7 @@ class MutalyzerService(ServiceBase): return ret #getGeneAndTranscript - @srpc(Mandatory.String, String, _returns=Array(TranscriptInfo)) + @srpc(Mandatory.Unicode, Unicode, _returns=Array(TranscriptInfo)) def getTranscriptsAndInfo(genomicReference, geneName=None): """ Given a genomic reference, return all its transcripts with their @@ -1081,7 +1081,7 @@ class MutalyzerService(ServiceBase): return ud #upLoadGenBankLocalFile - @srpc(Mandatory.String, _returns=Mandatory.String) + @srpc(Mandatory.Unicode, _returns=Mandatory.String) def uploadGenBankRemoteFile(url) : """ Not implemented yet. @@ -1089,7 +1089,7 @@ class MutalyzerService(ServiceBase): raise Fault('ENOTIMPLEMENTED', 'Not implemented yet') #upLoadGenBankRemoteFile - @srpc(Mandatory.String, Mandatory.String, Mandatory.Integer, + @srpc(Mandatory.Unicode, Mandatory.Unicode, Mandatory.Integer, Mandatory.Integer, _returns=Mandatory.String) def sliceChromosomeByGene(geneSymbol, organism, upStream, downStream) : @@ -1118,7 +1118,7 @@ class MutalyzerService(ServiceBase): return UD #sliceChromosomeByGene - @srpc(Mandatory.String, Mandatory.Integer, Mandatory.Integer, + @srpc(Mandatory.Unicode, Mandatory.Integer, Mandatory.Integer, Mandatory.Integer, _returns=Mandatory.String) def sliceChromosome(chromAccNo, start, end, orientation) : """ @@ -1201,7 +1201,7 @@ class MutalyzerService(ServiceBase): return 'pong' #ping - @srpc(Mandatory.String, Mandatory.String, _returns=Allele) + @srpc(Mandatory.Unicode, Mandatory.Unicode, _returns=Allele) def descriptionExtract(reference, observed): """ Extract the HGVS variant description from a reference sequence and an @@ -1253,7 +1253,7 @@ class MutalyzerService(ServiceBase): return map(cache_entry_to_soap, cache) #getCache - @srpc(Mandatory.String, _returns=Array(Mandatory.String)) + @srpc(Mandatory.Unicode, _returns=Array(Mandatory.String)) def getdbSNPDescriptions(rs_id): """ Lookup HGVS descriptions for a dbSNP rs identifier. diff --git a/requirements.txt b/requirements.txt index ab361e7d..08f2d5de 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ pyparsing==2.0.1 pytz==2013.9 requests==2.2.1 simplejson==3.3.3 --e git+https://github.com/LUMC/spyne.git@spyne-2.11.0-mutalyzer#egg=spyne +spyne==2.11.0 suds==0.4 wsgiref==0.1.2 xlrd==0.9.2 -- GitLab