1
2 """
3 Application class that implements pyFoamUpdateDictionary.py
4 """
5
6 import re
7 from os import path
8
9 from PyFoamApplication import PyFoamApplication
10
11 from PyFoam.RunDictionary.ParsedParameterFile import ParsedParameterFile
12 from PyFoam.Basics.DataStructures import DictProxy,TupleProxy
13
14 from PyFoam.Error import error,warning
15
18 description="""
19 Takes two dictionary and modifies the second one after the example of
20 the first. If the dictionaries do not have the same name, it looks for
21 the destination file by searching the equivalent place in the destination
22 case
23 """
24
25 PyFoamApplication.__init__(self,
26 args=args,
27 description=description,
28 usage="%prog [options] <source> <destination-case>",
29 nr=2,
30 changeVersion=False,
31 interspersed=True)
32
34 self.parser.add_option("--interactive",
35 action="store_true",
36 default=False,
37 dest="interactive",
38 help="Asks the user before applying changes")
39
40 self.parser.add_option("--clear-unused",
41 action="store_true",
42 default=False,
43 dest="clear",
44 help="Removes all the dictionary entries that are not in the source")
45
46 self.parser.add_option("--add-missing",
47 action="store_true",
48 default=False,
49 dest="add",
50 help="Add all the dictionary entries that are not in the destination")
51
52 self.parser.add_option("--append-lists",
53 action="store_true",
54 default=False,
55 dest="append",
56 help="Append to lists if they are shorter than the original")
57
58 self.parser.add_option("--shorten-lists",
59 action="store_true",
60 default=False,
61 dest="shorten",
62 help="Shortens lists if they are longer than the original")
63
64 self.parser.add_option("--all",
65 action="store_true",
66 default=False,
67 dest="all",
68 help="Do all the editing commands: clear, add, shorten and append")
69
70 self.parser.add_option("--test",
71 action="store_true",
72 default=False,
73 dest="test",
74 help="Does not write the file but only prints it to the screen")
75
76 self.parser.add_option("--not-equal",
77 action="store_true",
78 default=False,
79 dest="notequal",
80 help="Allow source and destination to have different names")
81
82 self.parser.add_option("--verbose",
83 action="store_true",
84 default=False,
85 dest="verbose",
86 help="Print every change that is being made")
87
88 self.parser.add_option("--min-recursion",
89 action="store",
90 default=0,
91 type="int",
92 dest="min",
93 help="Minimum depth of the recursive decent into dictionaries at which 'editing' should start (default: %default)")
94
95 self.parser.add_option("--max-recursion",
96 action="store",
97 default=100,
98 type="int",
99 dest="max",
100 help="Maximum depth of the recursive decent into dictionaries (default: %default)")
101
102 self.parser.add_option("--no-header",
103 action="store_true",
104 default=False,
105 dest="noHeader",
106 help="Don't expect a header while parsing")
107
108 self.parser.add_option("--boundary",
109 action="store_true",
110 default=False,
111 dest="boundaryDict",
112 help="Expect that this file is a boundary dictionary")
113 self.parser.add_option("--list",
114 action="store_true",
115 default=False,
116 dest="listDict",
117 help="Expect that this file only contains a list")
118
119 - def ask(self,*question):
120 if not self.opts.interactive:
121 return False
122 else:
123 print "QUESTION:",
124 for q in question:
125 print q,
126
127 answer=None
128 while answer!="y" and answer!="n":
129 answer=raw_input(" [Y]es or [N]no ? ").strip()[0].lower()
130 return answer=="y"
131
133 if depth>self.opts.max:
134 if self.opts.verbose:
135 print "- "*depth,"Recursion ended"
136 return
137
138 for i in range(min(len(source),len(dest))):
139 if type(source[i])==type(dest[i]) and type(source[i]) in [dict,DictProxy]:
140 if self.opts.verbose:
141 print "- "*depth,"Entering dict nr.",i
142 self.workDict(source[i],dest[i],depth+1)
143 if self.opts.verbose:
144 print "- "*depth,"Leaving dict nr.",i
145 elif type(source[i])==type(dest[i]) and type(source[i]) in [tuple,TupleProxy,list]:
146 if self.opts.verbose:
147 print "- "*depth,"Entering tuple nr.",i
148 self.workList(source[i],dest[i],depth+1)
149 if self.opts.verbose:
150 print "- "*depth,"Leaving tuple nr.",i
151 elif self.opts.interactive:
152 if source[i]!=dest[i]:
153 if self.ask("Replace for index",i,"the value",dest[i],"with the value",source[i]):
154 dest[i]=source[i]
155
156 if len(source)<len(dest) and self.opts.shorten:
157 if self.ask("Clip [",len(source),":] with the values ",dest[len(source):],"from the list"):
158 if self.opts.verbose:
159 print "- "*depth,"Clipping",len(dest)-len(source),"entries starting with",len(source)
160 dest=dest[0:len(source)]
161 elif len(source)>len(dest) and self.opts.append:
162 if self.ask("Append [",len(dest),":] with the values ",source[len(dest):],"to the list"):
163 if self.opts.verbose:
164 print "- "*depth,"Appending",len(source)-len(dest),"entries starting with",len(dest)
165 dest+=source[len(dest):]
166
168 if depth>self.opts.max:
169 if self.opts.verbose:
170 print "- "*depth,"Recursion ended"
171 return
172
173 if depth>=self.opts.min:
174 doIt=True
175 else:
176 doIt=False
177
178 for name in source:
179 if name not in dest:
180 if self.opts.add and doIt:
181 if self.ask("Add the key",name,"with value",source[name]):
182 if self.opts.verbose:
183 print "- "*depth,"Adding",name
184 dest[name]=source[name]
185 elif type(source[name]) in [dict,DictProxy]:
186 if type(dest[name]) not in [dict,DictProxy]:
187 error("Entry",name,"is not a dictionary in destination (but in source)")
188 if self.opts.verbose:
189 print "- "*depth,"Entering dict ",name
190 self.workDict(source[name],dest[name],depth+1)
191 if self.opts.verbose:
192 print "- "*depth,"Leaving dict ",name
193 elif type(source[name])==type(dest[name]) and type(dest[name]) in [tuple,TupleProxy,list]:
194 if self.opts.verbose:
195 print "- "*depth,"Entering tuple ",name
196 self.workList(source[name],dest[name],depth+1)
197 if self.opts.verbose:
198 print "- "*depth,"Leaving tuple ",name
199 elif self.opts.interactive:
200 if source[name]!=dest[name]:
201 if self.ask("Replace for key",name,"the value",dest[name],"with the value",source[name]):
202 dest[name]=source[name]
203 else:
204 if self.opts.verbose:
205 print "- "*depth,"Nothing done for",name
206
207 if self.opts.clear and doIt:
208 weg=[]
209 for name in dest:
210 if name not in source:
211 weg.append(name)
212
213 for name in weg:
214 if self.ask("Remove the key",name,"with the value",dest[name]):
215 if self.opts.verbose:
216 print "- "*depth,"Removing",name
217 del dest[name]
218
220 sName=path.abspath(self.parser.getArgs()[0])
221 dName=path.abspath(self.parser.getArgs()[1])
222
223 if self.opts.all:
224 self.opts.append=True
225 self.opts.shorten=True
226 self.opts.add=True
227 self.opts.clear=True
228
229 try:
230 source=ParsedParameterFile(sName,backup=False,noHeader=self.opts.noHeader,boundaryDict=self.opts.boundaryDict,listDict=self.opts.listDict)
231 except IOError,e:
232 self.error("Problem with file",sName,":",e)
233
234 if not self.opts.notequal and path.basename(sName)!=path.basename(dName):
235 found=False
236 parts=sName.split(path.sep)
237 for i in range(len(parts)):
238 tmp=apply(path.join,[dName]+parts[-(i+1):])
239
240 if path.exists(tmp):
241 found=True
242 dName=tmp
243 warning("Found",dName,"and using this")
244 break
245
246 if not found:
247 error("Could not find a file named",path.basename(sName),"in",dName)
248
249 if path.samefile(sName,dName):
250 error("Source",sName,"and destination",dName,"are the same")
251
252 try:
253 dest=ParsedParameterFile(dName,backup=False,noHeader=self.opts.noHeader,boundaryDict=self.opts.boundaryDict,listDict=self.opts.listDict)
254 except IOError,e:
255 self.error("Problem with file",dName,":",e)
256
257 if self.opts.interactive:
258 self.opts.verbose=True
259
260 if not self.opts.boundaryDict and not self.opts.listDict:
261 self.workDict(source.content,dest.content,1)
262 else:
263 self.workList(source.content,dest.content,1)
264
265 if self.opts.test or self.opts.interactive:
266 print str(dest)
267
268 if not self.opts.test and self.ask("\n Write this file to disk"):
269 dest.writeFile()
270