Package PyFoam :: Package Applications :: Module UpdateDictionary
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.Applications.UpdateDictionary

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