Source code for PyFoam.Basics.FoamFileGenerator

#  ICE Revision: $Id$
"""Transform a Python data-structure into a OpenFOAM-File-Representation"""

from PyFoam.Error import error,PyFoamException
from PyFoam.Basics.DataStructures import Vector,Field,Dimension,TupleProxy,DictProxy,Tensor,SymmTensor,Unparsed,UnparsedList,Codestream,DictRedirection,BinaryList,BoolProxy

from PyFoam.ThirdParty.six import string_types,integer_types
from collections import OrderedDict

[docs]class FoamFileGenerator(object): """Class that generates a OpenFOAM-compatible representation of a data-structure""" primitiveTypes=[SymmTensor,Tensor,Vector,Dimension,Field,Unparsed] def __init__(self, data, header=None, longListThreshold=20, useFixedType=True): """:param data: data structure that will be turned into a Foam-compatible file :param header: header information that is to be prepended :param longListThreshold: Threshold for lists before they are considered long. This means that they are prefixed with the number of elements. If the threshold is 0 or None then no list is considered long """ self.data=data self.header=header self.longListThreshold=longListThreshold self.useFixedType=useFixedType def __str__(self): return self.makeString() def __quoteString(self,val): """Quote the string if it contains illegal characters""" if len(val)==0: return val if val[0] in ["'",'"']: return val quote=False for c in r'\{}/;"': # list from word::stripInvalid if val.find(c)>=0: quote=True break if quote: if val.find('"')>=0: return "'"+val+"'" else: return '"'+val+'"' else: return val
[docs] def makeString(self,firstLevel=False): """turns the data into a string""" result="" if self.header: result+="FoamFile\n{\n"+self.strDict(self.header,indent=1)+"}\n\n" if type(self.data) in [dict,DictProxy,OrderedDict]: result+=self.strDict(self.data,firstLevel=firstLevel) elif type(self.data) in [tuple,TupleProxy]: result+=self.strTuple(self.data) elif type(self.data) in [list,UnparsedList,BinaryList]: result+=self.strList(self.data) elif self.data is None: raise FoamFileGeneratorError("<None> found") else: result+=self.strPrimitive(self.data) return result
[docs] def strPrimitive(self,pri): if type(pri)==bool: if pri: return "yes" else: return "no" elif type(pri)==BoolProxy: return str(pri) elif isinstance(pri,string_types): return self.__quoteString(pri) elif isinstance(pri,integer_types+(float,)): return str(pri) elif pri.__class__ in self.primitiveTypes: return str(pri) elif type(pri)==DictRedirection: return str(pri()) else: error("List, Dict or valid primitve expected,",type(pri),"found in",pri)
[docs] def strDict(self,dic,indent=0,firstLevel=False): s="" if type(dic)==DictProxy: order=dic._order else: order=list(dic.keys()) if not isinstance(dic,(OrderedDict,)): order.sort() for k in order: if type(k)==DictRedirection: v=k else: try: v=dic[k] except KeyError: v=dic.getRegexpValue(k) end="\n" if type(dic)==DictProxy: end=dic.getDecoration(k)+"\n" if firstLevel: end+="\n" # remove trailing spaces end="\n".join([part.rstrip() for part in end.split("\n")]) if type(k)==int: s+=v continue if str(k).find("anonymValue")==0: k="" s+=(" "*indent)+str(k) if isinstance(v,string_types): if type(v)==Codestream: s+="\n" s+=" "*indent s+=str(v) s+=";"+end else: s+=" "+self.__quoteString(v)+";"+end elif type(v) in [dict,DictProxy,OrderedDict]: s+="\n"+(" "*indent)+"{\n" s+=self.strDict(v,indent+2) s+=(" "*indent)+"}"+end elif type(v) in [list,UnparsedList]: s+="\n" s+=self.strList(v,indent+2) if s[-1]=="\n": s=s[:-1] s+=";"+end elif isinstance(v,(tuple,TupleProxy)): s+=" "+self.strTuple(v,indent+2)+";"+end elif type(v) in [bool,BoolProxy]: if v: s+=" yes;\n" else: s+=" no;\n" elif isinstance(v,integer_types+(float,)): s+=" "+str(v)+";"+end elif v.__class__ in self.primitiveTypes: s+=" "+str(v)+";"+end elif type(v)==type(None): s+=" /* empty */ ;"+end elif type(v)==DictRedirection: s+=";"+end else: error("Unhandled type",type(v)," for",v) return s
[docs] def strList(self,lst,indent=0): s="" if type(lst)==UnparsedList: s+=(" "*indent)+str(len(lst))+" (" s+=lst.data if lst.data[-1]!="\n": s+="\n" s+=(" "*indent)+")\n" return s elif type(lst)==BinaryList: s+=(" "*indent)+str(len(lst))+" (" s+=lst.data s+=")" return s theLen=len(lst) if len(lst)>2 and len(lst)%2==0: if isinstance(lst[0],string_types) and (type(lst[1]) in [dict,DictProxy]): theLen=len(lst)/2 isFixedType=False if self.useFixedType and (len(lst)==3 or len(lst)==9 or len(lst)==6): isFixedType=True for l in lst: try: float(l) except (ValueError,TypeError): isFixedType=False if isFixedType: s+="("+" ".join(["%g"%v for v in lst])+")" else: if self.longListThreshold: if theLen>self.longListThreshold: s+=(" "*indent)+str(theLen)+"\n" s+=(" "*indent)+"(\n" for v in lst: if isinstance(v,string_types): s+=(" "*(indent+2))+v+"\n" elif type(v) in [dict,DictProxy]: s+="\n"+(" "*(indent+2))+"{\n" s+=self.strDict(v,indent+4) s+="\n"+(" "*(indent+2))+"}\n" elif type(v) in [list,UnparsedList]: s+="\n" s+=self.strList(v,indent+2) elif type(v)==tuple: s+=" "+self.strTuple(v,indent+2)+" " else: s+=(" "*(indent+2))+str(v)+"\n" s+=(" "*indent)+")\n" return s
[docs] def strTuple(self,lst,indent=0): s="" for v in lst: if isinstance(v,string_types): s+=v+" " elif type(v) in [dict,DictProxy]: s+="{\n" s+=self.strDict(v,indent+4) s+=(" "*(indent+2))+"} " elif type(v) in [list,UnparsedList]: s+=" " s+=self.strList(v,indent+2) else: s+=(" "*(indent+2))+str(v)+" " return s
[docs]def makeString(data): return str(FoamFileGenerator(data))
[docs]class FoamFileGeneratorError(PyFoamException): def __init__(self,descr): PyFoamException.__init__(self,descr)
# Should work with Python3 and Python2