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