1
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
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
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
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
92 """ closes the file"""
93 self.fh.close()
94 self.fh=None
95
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
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
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
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
151 """ Parse a string that is to be the content, to be overriden
152 by the sub-classes"""
153
154 return cnt
155
157 """Build a string from self.content, to be overriden by sub-classes"""
158
159 return self.content
160
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
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
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
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
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
285
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
322
326
327
328