Source code for ccpnmodel.ccpncore.memops.scripts.xmlio.PyXmlMapWrite

"""Module Documentation here

"""
#=========================================================================================
# Licence, Reference and Credits
#=========================================================================================
__copyright__ = "Copyright (C) CCPN project (http://www.ccpn.ac.uk) 2014 - 2017"
__credits__ = ("Wayne Boucher, Ed Brooksbank, Rasmus H Fogh, Luca Mureddu, Timothy J Ragan & Geerten W Vuister")
__licence__ = ("CCPN licence. See http://www.ccpn.ac.uk/v3-software/downloads/license",
               "or ccpnmodel.ccpncore.memops.Credits.CcpnLicense for licence text")
__reference__ = ("For publications, please use reference from http://www.ccpn.ac.uk/v3-software/downloads/license",
               "or ccpnmodel.ccpncore.memops.Credits.CcpNmrReference")

#=========================================================================================
# Last code modification
#=========================================================================================
__modifiedBy__ = "$modifiedBy: CCPN $"
__dateModified__ = "$dateModified: 2017-07-07 16:33:25 +0100 (Fri, July 07, 2017) $"
__version__ = "$Revision: 3.0.0 $"
#=========================================================================================
# Created
#=========================================================================================

__author__ = "$Author: CCPN $"
__date__ = "$Date: 2017-04-07 10:28:48 +0000 (Fri, April 07, 2017) $"
#=========================================================================================
# Start of code
#=========================================================================================

"""
======================COPYRIGHT/LICENSE START==========================

PyXmlMapWrite.py: Code generation for CCPN framework

Copyright (C) 2005 Rasmus Fogh (CCPN Project)

=======================================================================

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
 
A copy of this license can be found in ../../../license/GPL.license
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
 
You should have received a copy of the GNU General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA


======================COPYRIGHT/LICENSE END============================

for further information, please contact :

- CCPN website (http://www.ccpn.ac.uk/)

- email: ccpn@bioc.cam.ac.uk

=======================================================================

If you are using this software for academic purposes, we suggest
quoting the following references:

===========================REFERENCE START=============================
R. Fogh, J. Ionides, E. Ulrich, W. Boucher, W. Vranken, J.P. Linge, M.
Habeck, W. Rieping, T.N. Bhat, J. Westbrook, K. Henrick, G. Gilliland,
H. Berman, J. Thornton, M. Nilges, J. Markley and E. Laue (2002). The
CCPN project: An interim report on a data model for the NMR community
(Progress report). Nature Struct. Biol. 9, 416-418.

Rasmus H. Fogh, Wayne Boucher, Wim F. Vranken, Anne
Pajon, Tim J. Stevens, T.N. Bhat, John Westbrook, John M.C. Ionides and
Ernest D. Laue (2005). A framework for scientific data modeling and automated
software development. Bioinformatics 21, 1678-1684.

===========================REFERENCE END===============================

"""
from ccpnmodel.ccpncore.memops.metamodel import MetaModel
from ccpnmodel.ccpncore.memops.metamodel import Constants as metaConstants
from ccpnmodel.ccpncore.memops.scripts.xmlio.XmlMapWrite import XmlMapWrite
from ccpnmodel.ccpncore.memops.scripts.core.PyLanguage import PyLanguage
from ccpnmodel.ccpncore.memops.scripts.core.PyType import PyType

MemopsError = MetaModel.MemopsError


[docs]def writeXmlIo(modelPortal, rootFileName=None, rootDirName=None, releaseVersion=None, **kw): """write Python XML I/O mappings and code Only function that should be called directly by 'make' scripts etc. """ pyXmlWrite = PyXmlMapWrite(modelPortal=modelPortal, rootFileName=rootFileName, rootDirName=rootDirName, releaseVersion=releaseVersion, scriptName='PyXmlMapWrite', **kw) pyXmlWrite.processModel()
[docs]class PyXmlMapWrite(PyLanguage, PyType, XmlMapWrite): def __init__(self, **kw): self.addModelFlavour('language', 'python') self.baseName = 'xml' for (tag, val) in kw.items(): if not hasattr(self, tag): setattr(self, tag, val) super(PyXmlMapWrite, self).__init__() ########################################################################### ########################################################################### # overrides XmlMapWrite
[docs] def addXmlStringFunctions(self, dictName, typeCode): if typeCode == 'Boolean': self.setDictEntry(dictName, self.toLiteral('toStr'), 'bool2str') self.setDictEntry(dictName, self.toLiteral('cnvrt'), 'str2bool') elif typeCode == 'String': self.setDictEntry(dictName, self.toLiteral('toStr'), self.toLiteral('text')) self.setDictEntry(dictName, self.toLiteral('cnvrt'), self.toLiteral('text')) else: self.setDictEntry(dictName, self.toLiteral('toStr'), 'basicDataTypes.%s.toString' % typeCode) self.setDictEntry(dictName, self.toLiteral('cnvrt'), 'basicDataTypes.%s.fromString' % typeCode)
########################################################################### ########################################################################### # overrides XmlMapWrite
[docs] def addXmlClassCreation(self, dictName, clazz, package=None): if package is not None: pp = clazz.container if pp in package.accessedPackages: self.write("import %s" % self.getImportName(pp, subDirs=[metaConstants.apiCodeDir]) ) self.setDictEntry(dictName, self.toLiteral('class'), self.getImportName(clazz, subDirs=[metaConstants.apiCodeDir]))
########################################################################### ########################################################################### # overrides XmlMapWrite
[docs] def addDefaultValues(self, dictName, elemMap, elem): val = elemMap.get('default') if val is not None: self.setDictEntry(dictName, self.toLiteral('default'), self.toLiteral(val))
########################################################################### ########################################################################### # overrides XmlMapWrite
[docs] def initLeafPackage(self, package): """ write API header for package containing actual code """ super(PyXmlMapWrite, self).initLeafPackage(package) self.write( """ from ccpnmodel.ccpncore.memops.metamodel.Constants import baseDataTypeModule as basicDataTypes NaN = float('NaN')""" ) # import own API package self.writeComment("\n Current package api") self.write("import %s" % self.getImportName(package, subDirs=[metaConstants.apiCodeDir])) if package is self.implPackage: self.writeNewline() self.writeComment('ApiError import') self.writeOne('from ccpnmodel.ccpncore.memops.ApiError import ApiError') self.writeNewline() # set up boolean converters self.write(""" def bool2str(value): return value and 'true' or 'false' def str2bool(value): if value in ('True', 'true', '1'): return True elif value in ('False', 'false', '0'): return False else: raise ApiError("String '%s' is not legal for a Boolean" % value) """) # define global functions self.write(""" _globalMapping = {} def getGlobalMap(oldVersionStr=None): from ccpnmodel.ccpncore.memops.Version import currentModelVersion newVersionStr = str(currentModelVersion) if oldVersionStr is None: oldVersionStr = newVersionStr versionMapping = _globalMapping.get(oldVersionStr) if versionMapping is None: versionMapping = {} _globalMapping[oldVersionStr] = versionMapping makeMapping(versionMapping) """) # load maps for all other known packages for pp in self.modelPortal.leafPackagesByImport()[1:]: ss = self.getImportName(pp, package) self.write(""" import %s %s.makeMapping(versionMapping) """ % (ss, ss)) self.write(""" # adjust Io map for compatibility considerations if oldVersionStr != newVersionStr: from ccpnmodel.ccpncore.memops.format.compatibility.Converters1 import modifyIoMap # versions are different - compatibility needed modifyIoMap(oldVersionStr, versionMapping) # return versionMapping """) # start makeMapping function ss = self.localVarNames['globalMap'] self.startFunc('makeMapping', params=[ss], docString="generates XML I/O mapping for package %s, adding it to %s" % (self.prefix, ss) ) if package is not self.implPackage: self.write(""" from %s import bool2str, str2bool """ % self.getImportName(self.implPackage, package))
########################################################################### ########################################################################### # overrides XmlMapWrite
[docs] def writeFileHeader(self, package): self.writeMultilineComment( (self.getVersionString(metaobj=package) + '\n' + self.getCreditsString(metaobj=package, programType='XML-I/O-mapping')), compress=False )
########################################################################### ########################################################################### # overrides XmlMapWrite
[docs] def endLeafPackage(self, package): self.endFunc() if package is self.implPackage: # saveToStream self.writeSaveToStream('CCPN Python XmlIO') # loadFromStream self.writeLoadFromStream('elementtree') super(PyXmlMapWrite, self).endLeafPackage(package)
########################################################################### ########################################################################### # SaveToStream function # overrides XmlMapWrite
[docs] def writeSaveToStreamBody(self, originator, indentBySpaces = 2): self.write(''' import time strapp = stream.write indents = {0:''} if mapping is None: mapping = getGlobalMap()[topObject.metaclass.container.shortName] ''') super(PyXmlMapWrite, self).writeSaveToStreamBody(originator, indentBySpaces=indentBySpaces)
########################################################################### ########################################################################### # SaveToStream function # implements XmlMapWrite
[docs] def streamWrite(self, s): self.write('strapp(%s)' % s)
########################################################################### ########################################################################### # SaveToStream function # implements XmlMapWrite
[docs] def streamWriteStartElement(self, element, closeElement = True, newLine = True, **attrs): keys = attrs.keys() strs = [] strs2 = [element] for key in keys: # if key == '_ID': # strs.append(' %s="_%%s"' % key) # else: strs.append(' %s="%%s"' % key) strs2.append(attrs[key]) if closeElement: if newLine: strs.append('>\\n') else: strs.append('>') self.streamWrite("'%%s<%%s%s' %% (indent, %s)" % (''.join(strs), ', '.join(strs2)))
########################################################################### ########################################################################### # SaveToStream function # implements XmlMapWrite
[docs] def streamWriteEndElement(self, element, newLine = True, doIndent = False): if newLine: t = '\\n' else: t = '' if doIndent: s = "'%%s</%%s>%s' %% (indent, %s)" % (t, element) else: s = "'</%%s>%s' %% %s" % (t, element) self.streamWrite(s)
########################################################################### ########################################################################### # SaveToStream function # implements XmlMapWrite
[docs] def streamWriteAttr(self, key, value): self.streamWrite('\' %%s="%%s"\' %% (%s, %s)' % (key, value))
########################################################################### ########################################################################### # SaveToStream function # implements XmlMapWrite
[docs] def streamWriteValue(self, value): self.streamWrite('\' %%s\' %% %s' % value)
########################################################################### ########################################################################### # SaveToStream function # implements XmlMapWrite
[docs] def streamWriteComment(self, comment): self.streamWrite("\"<!--%%s-->\\n\" %% %s.replace('--','\-\-')" % comment)
########################################################################### ########################################################################### # SaveToStream function # implements XmlMapWrite
[docs] def streamNonTextToString(self, value): self.writeComment('non-string simple type - toStr is conversion function') self.writeOne('%s = toStr(%s)' % (value, value))
########################################################################### ########################################################################### # SaveToStream function # implements XmlMapWrite
[docs] def streamIndent(self, increasing): if increasing: self.writeOne('nIndent += indentBySpaces') self.writeOne("indent = indents.setdefault(nIndent, nIndent*' ')") else: self.writeOne('nIndent -= indentBySpaces') self.writeOne('indent = indents[nIndent]')
########################################################################### ########################################################################### # SaveToStream function # implements XmlMapWrite
[docs] def streamOrderedCollection(self, var): self.write(''' if tmpMap['type'] == 'child': items = list(%s.items()) items.sort() ll = [x[1] for x in items] else: ll = list(%s) ll.reverse() # for reproducibility stack.extend(ll) mapStack.extend(tmpCont[x.__class__.__name__] for x in ll) ''' % (var, var))
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def writeLoadFromStreamStart(self): pass
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def writeLoadFromStreamMain(self): self.writeLoadFromStreamBody()
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def writeLoadFromStreamHandleError(self): self.write(''' if elem: tag = elem.tag else: tag = 'None' ''') self.writeLoadFromStreamErrorBody()
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def writeLoadFromStreamEnd(self): self.writeLoadFromStreamExtraFunctions()
########################################################################### ########################################################################### # LoadFromStream function # overrides XmlMapWrite
[docs] def streamStartParse(self): super(PyXmlMapWrite, self).streamStartParse() # TBD: optimisations involving stack.append, stack.pop self.write(''' # needed for error handling elem = None ''') # LOOP H self.write(''' # get elementtree NBNB TBD to be redone to allow for different sources from xml.etree import ElementTree # LOOP H for event, elem in ElementTree.iterparse(stream, events=("start", "end")): ''') self.indent += self.INDENT
########################################################################### ########################################################################### # LoadFromStream function # overrides XmlMapWrite
[docs] def streamStartElement(self): # IF BLOCK 100 self.writeComment('IF BLOCK 100') self.startIf(self.comparison('event', '==', self.toLiteral('start'))) super(PyXmlMapWrite, self).streamStartElement()
########################################################################### ########################################################################### # LoadFromStream function # overrides XmlMapWrite
[docs] def streamEndElement(self): # IF BLOCK 100 self.elseIf() self.writeComment('IF BLOCK 100') super(PyXmlMapWrite, self).streamEndElement() # clean out to save memory# # self.writeComment('clean out to save memory') # self.startIf('clearElem') # self.writeOne('elem.clear()') # self.endIf() # IF BLOCK 100 self.endIf()
########################################################################### ########################################################################### # LoadFromStream function # overrides XmlMapWrite
[docs] def streamEndParse(self): # LOOP H self.indent -= self.INDENT super(PyXmlMapWrite, self).streamEndParse()
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamDoCompatibility(self): self.writeOne('from ccpnmodel.ccpncore.memops.format.compatibility import Converters1') self.writeOne('Converters1.minorPostProcess(fileVersion, result, delayDataDict, objectDict, mapping)')
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite # def streamSetupCompatibility(self): # # self.writeComment('Set up for compatibility - keeping XML parse tree') # self.setVar('clearElem', self.getDictEntry('mapping', '"clearXmlElements"')) # self.startIf('clearElem') # self.setVar('topObjElem', 'elem') # self.elseIf() # self.setVar('topObjElem', None) # self.endIf() ########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamElementTag(self, state='start'): return 'elem.tag'
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamElementText(self): return 'elem.text'
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamElementSplitText(self, var, cnvrt = None): if cnvrt: self.write(''' if cnvrt == 'text': %s = elem.text.split() else: %s = [%s(x) for x in elem.text.split()] ''' % (var, var, cnvrt)) else: self.writeOne('%s = elem.text.split()' % var)
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamElementAttr(self, key): return 'elem.get(%s)' % key
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamElementSetSkip(self, setToNone = False): if setToNone: elem = 'None' else: elem = 'elem' self.writeOne('skipElement = %s' % elem)
# if setToNone: # self.startIf('clearElem') # self.writeOne('elem.clear()') # self.endIf() ########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamElementIsSkip(self, doReset=True): return self.comparison('elem', 'is', 'skipElement')
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamNextElement(self): self.writeOne('continue')
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamStartAttributeLoop(self, tag, value): self.startLoop('(%s, %s)' % (tag, value), 'elem.items()', isUnique=False, isOrdered=False)
########################################################################### ########################################################################### # SaveToStream function # LoadFromStream function # implements XmlMapWrite
[docs] def streamGetValue(self, var, name, defaultValue = None, keyIsMandatory = False, getChildAsDict = False): return self.getDictEntry('%s.__dict__' % var, name, defaultValue=defaultValue, keyIsMandatory=keyIsMandatory)
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamSetValue(self, var, name, value, useDirectSet=True): if useDirectSet: self.writeOne('%s.__dict__[%s] = %s' % (var, name, value)) else: self.writeOne('setattr(%s, %s, %s)' % (var, name, value))
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamConvertStringToValue(self, cnvrt, value): return '%s(%s)' % (cnvrt, value)
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamOverrideOff(self, var): self.writeOne("del %s.__dict__['override']" % var)
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamFoundClosingTag(self): self.writeOne('break')
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamHaveEarlyExit(self): self.writeOne('break')
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite ########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamCallConstructor(self, var, constructor, parent = None, castType = None, **attrlinks): ss = ['%s=%s' % (key, value) for (key, value) in attrlinks.items()] ss = ', '.join(ss) if parent: if ss: tt = ', ' else: tt = '' self.writeOne('%s = %s(%s%s%s)' % (var, constructor, parent, tt, ss)) else: self.writeOne('%s = %s(%s)' % (var, constructor, ss))
########################################################################### ########################################################################### # LoadFromStream function # implements XmlMapWrite
[docs] def streamAddAll(self, collectionToBeAdded, collectionToBeAddedTo): self.writeOne('%s.extend(%s)' % (collectionToBeAddedTo, collectionToBeAdded))
########################################################################### ########################################################################### # LoadFromStream function
[docs] def streamObjDictKey(self, obj, isMetaClass): if isMetaClass: return obj else: return 'id(%s)' % obj
########################################################################### ########################################################################### # LoadFromStream function
[docs] def streamInitLoadingMaps(self): self.write(''' from ccpnmodel.ccpncore.memops.Version import currentModelVersion newVersionStr = str(currentModelVersion) from ccpnmodel.ccpncore.xml.memops.Implementation import getGlobalMap globalMapping = getGlobalMap(fileVersion) # handle compatibility considerations if fileVersion == newVersionStr: needCompatibility = False else: needCompatibility = True ''')
########################################################################### ########################################################################### # SaveToStream function # LoadFromStream function # implements XmlMapWrite
[docs] def streamStartFunc(self, funcname, params=None, docString='', returnString='', returnType=None, throwsApiError=True): if not params: params = () pars = [] for param in params: if len(param) == 4: ss = '=%s' % param[3] else: ss = '' par = '%s%s' % (param[0], ss) pars.append(par) self.startFunc(funcname, params=pars, docString=docString)
########################################################################### ########################################################################### # must be here because if in XmlMapWrite then not picked up # because of order of superclasses # overrides LanguageInterface
[docs] def raiseApiError(self, errorMsg, obj = None, obj2 = None, obj3 = None): super(PyXmlMapWrite, self).raiseApiError(errorMsg, obj=obj, obj2=obj2, obj3=obj3, inOp=False)