Package PyFoam :: Package RunDictionary :: Module FileBasis
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.RunDictionary.FileBasis

  1  #  ICE Revision: $Id$ 
  2  """Basis for the handling of OpenFOAM-files 
  3   
  4  Transparently accepts gnuzipped files""" 
  5   
  6  import os,re 
  7  from os import path 
  8  from tempfile import mktemp 
  9  import gzip 
 10   
 11   
 12  from PyFoam.Basics.Utilities import Utilities 
 13  from PyFoam.Basics.LineReader import LineReader 
 14   
 15  from PyFoam.Error import warning,error 
 16   
 17  from PyFoam.ThirdParty.six import PY3 
 18   
19 -class FileBasis(Utilities):
20 """ Base class for the other OpenFOAM--file-classes""" 21 22 removedString="//PyFoamRemoved: " 23 """Comment for lines that were overwritten by PyFoam-routines""" 24 25 addedString="//PyFoamAdded" 26 """Comment for lines that were added by PyFoam-routines""" 27
28 - def __init__(self,name,createZipped=True):
29 """@param name: Name of the file. If the field is zipped the .gz is 30 appended. Alternatively it can be a filehandle 31 @param createZipped: if the file doesnot exist: should it be created 32 as a zipped file?""" 33 if hasattr(name,"read"): 34 self.name=None 35 self.exists=True 36 self.zipped=None 37 self.fh=name 38 else: 39 self.name = path.abspath(name) 40 self.exists = False 41 42 if path.exists(self.name): 43 self.exists = True 44 self.zipped=False 45 if path.splitext(self.name)[1]==".gz": 46 self.zipped=True 47 elif path.exists(self.name+".gz"): 48 warning(self.name+".gz","and",self.name,"existing - using the unzipped") 49 elif path.exists(self.name+".gz"): 50 self.zipped=True 51 self.exists = True 52 else: 53 self.zipped=createZipped 54 55 if path.splitext(self.name)[1]==".gz": 56 self.name=self.name[:-3] 57 58 self.fh=None 59 self.content=None
60
61 - def realName(self):
62 """The full filename with appended .gz (if zipped)""" 63 if self.name: 64 if self.zipped: 65 return self.name+".gz" 66 else: 67 return self.name 68 else: 69 return str(self.fh)
70
71 - def baseName(self):
72 """Returns the basic file name (without .gz)""" 73 if self.name: 74 return path.basename(self.name) 75 else: 76 return path.basename(self.fh.name)
77
78 - def openFile(self,keepContent=False,mode="r"):
79 """opens the file. To be overloaded by derived classes""" 80 if not keepContent: 81 self.content=None 82 if self.name: 83 if self.zipped: 84 self.fh=gzip.open(self.name+".gz",mode) 85 else: 86 self.fh=open(self.name,mode) 87 else: 88 if mode!="r": 89 error("File-handle",str(self.fh),"can only be used with mode 'r'")
90
91 - def closeFile(self):
92 """ closes the file""" 93 self.fh.close() 94 self.fh=None
95
96 - def readFile(self):
97 """ read the whole File into memory""" 98 self.openFile() 99 txt=self.fh.read() 100 if PY3 and self.zipped: 101 txt=str(txt,"utf-8") 102 self.content=self.parse(txt) 103 self.closeFile()
104
105 - def writeFile(self,content=None):
106 """ write the whole File from memory 107 @param content: content that should replace the old content""" 108 if self.name: 109 if content!=None: 110 self.content=content 111 if self.content!=None: 112 self.openFile(keepContent=True,mode="w") 113 txt=str(self) 114 self.fh.write(self.encode(txt)) 115 self.closeFile() 116 else: 117 error("File-handle",str(self.fh),"can not be written")
118
119 - def encode(self,txt):
120 """Encode a string to byte if necessary (for Python3)""" 121 if PY3 and self.zipped: 122 return bytes(txt,"utf-8") 123 else: 124 return txt
125
126 - def writeFileAs(self,name):
127 """ Writes a copy of the file. Extends with .gz if the original 128 is zipped 129 @param name: Name under which the file is written""" 130 if self.name: 131 if path.abspath(self.name)==path.abspath(name): 132 warning(name,"and",self.name,"seem to be the same. Nothing done") 133 return 134 135 erase=False 136 if self.content==None: 137 erase=True 138 self.readFile() 139 140 tmp=self.name 141 fh=self.fh 142 self.name=name 143 self.writeFile() 144 self.name=tmp 145 self.fh=fh 146 147 if erase: 148 self.content=None
149
150 - def parse(self,cnt):
151 """ Parse a string that is to be the content, to be overriden 152 by the sub-classes""" 153 154 return cnt
155
156 - def __str__(self):
157 """Build a string from self.content, to be overriden by sub-classes""" 158 159 return self.content
160
161 - def __enter__(self):
162 """Making the 'with'-statement happy""" 163 return self
164
165 - def __exit__(self,typ,value,traceback):
166 """Making the 'with'-statement happy""" 167 if self.fh!=None: 168 self.closeFile()
169
170 - def makeTemp(self):
171 """creates a temporary file""" 172 if self.name: 173 fName=self.name 174 else: 175 fName=self.fh.name 176 177 fn=mktemp(dir=path.dirname(fName)) 178 if self.zipped: 179 fh=gzip.open(fn,"w") 180 else: 181 fh=open(fn,"w") 182 183 return fh,fn
184
185 - def writeEncoded(self,out,txt):
186 """Convert the text to 'bytes' is we encounter a zipped file""" 187 if PY3: 188 if type(out) is gzip.GzipFile: 189 txt=bytes(txt,"utf-8") 190 out.write(txt)
191
192 - def goTo(self,l,s,out=None,echoLast=False,stop=None):
193 """Read lines until a token is found 194 195 @param l: a LineReader object 196 @param s: the string to look for 197 @param out: filehandle to echo the lines to 198 @param stop: pattern that indicates that exp will never be found (only passed through to goMatch) 199 @param echoLast: echo the line with the string""" 200 exp=re.compile("( |^)"+s+"( |$)") 201 self.goMatch(l,exp,out=out,stop=stop) 202 if out!=None and echoLast: 203 self.writeEncoded(out,l.line+"\n")
204
205 - def goMatch(self,l,exp,out=None,stop=None):
206 """Read lines until a regular expression is matched 207 208 @param l: a LineReader object 209 @param exp: the expression to look for 210 @param out: filehandle to echo the lines to 211 @param stop: pattern that indicates that exp will never be found 212 @return: match-object if exp is found, the line if stop is found and None if the end of the file is reached""" 213 while l.read(self.fh): 214 m=exp.match(l.line) 215 if m!=None: 216 return m 217 elif stop!=None: 218 if stop.match(l.line): 219 return l.line 220 if out!=None: 221 self.writeEncoded(out,l.line+"\n") 222 223 return None
224
225 - def copyRest(self,l,out):
226 """Copy the rest of the file 227 228 @param l: a LineReader object 229 @param out: filehandle to echo the lines to""" 230 while l.read(self.fh): 231 self.writeEncoded(out,l.line+"\n")
232
233 - def purgeFile(self):
234 """Undo all the manipulations done by PyFOAM 235 236 Goes through the file and removes all lines that were added""" 237 if not self.name: 238 error("File-handle",str(self.fh),"can not be purged") 239 240 rmExp= re.compile("^"+self.removedString+"(.*)$") 241 addExp=re.compile("^(.*)"+self.addedString+"$") 242 243 l=LineReader() 244 self.openFile() 245 246 (fh,fn)=self.makeTemp() 247 248 while l.read(self.fh): 249 toPrint=l.line 250 251 m=addExp.match(l.line) 252 if m!=None: 253 continue 254 255 m=rmExp.match(l.line) 256 if m!=None: 257 toPrint=m.group(1) 258 259 self.writeEncoded(fh,toPrint+"\n") 260 261 self.closeFile() 262 fh.close() 263 os.rename(fn,self.name)
264
265 - def getCaseDir(self):
266 """Return the path to the case of this file (if any valid case is found). 267 Else return None""" 268 269 if self.name: 270 fName=self.name 271 else: 272 fName=self.fh.name 273 274 from .SolutionDirectory import NoTouchSolutionDirectory 275 276 caseDir=None 277 comp=path.split(fName)[0] 278 while len(comp)>1: 279 if NoTouchSolutionDirectory(comp).isValid(): 280 caseDir=comp 281 break 282 comp=path.split(comp)[0] 283 284 return caseDir
285
286 -class FileBasisBackup(FileBasis):
287 """A file with a backup-copy""" 288 289 counter={} 290
291 - def __init__(self,name,backup=False,createZipped=True):
292 """@param name: The name of the parameter file 293 @type name: str 294 @param backup: create a backup-copy of the file 295 @type backup: boolean""" 296 297 if hasattr(name,"read"): 298 if backup: 299 warning(str(name),"is a file-handle. No backup possible") 300 backup=False 301 302 FileBasis.__init__(self,name,createZipped=createZipped) 303 304 if backup: 305 self.backupName=self.name+".backup" 306 try: 307 FileBasisBackup.counter[self.name]+=1 308 except KeyError: 309 FileBasisBackup.counter[self.name]=1 310 self.copyfile(self.name,self.backupName) 311 else: 312 self.backupName=None
313
314 - def restore(self):
315 """if a backup-copy was made the file is restored from this""" 316 if self.backupName!=None: 317 FileBasisBackup.counter[self.name]-=1 318 if FileBasisBackup.counter[self.name]==0: 319 self.copyfile(self.backupName,self.name) 320 self.remove(self.backupName) 321 del FileBasisBackup.counter[self.name]
322
323 -def exists(name):
324 f=FileBasis(name) 325 return f.exists
326 327 # Should work with Python3 and Python2 328