1
2 """
3 Application class that implements pyFoamCompareDictionary.py
4 """
5
6 import re
7 from os import path
8
9 import sys
10
11 from .PyFoamApplication import PyFoamApplication
12
13 from PyFoam.RunDictionary.ParsedParameterFile import ParsedParameterFile,PyFoamParserError
14 from PyFoam.Basics.DataStructures import DictProxy,Dimension,Tensor,SymmTensor,Vector,Field,TupleProxy
15 from PyFoam.Basics.FoamFileGenerator import makeString
16
17 from PyFoam.Error import error,warning
18
19 from .CommonParserOptions import CommonParserOptions
20
21 from PyFoam.Basics.TerminalFormatter import TerminalFormatter
22
23 from PyFoam.ThirdParty.six import print_,integer_types
24
25 f=TerminalFormatter()
26 f.getConfigFormat("source",shortName="src")
27 f.getConfigFormat("destination",shortName="dst")
28 f.getConfigFormat("difference",shortName="diff")
29 f.getConfigFormat("error",shortName="name")
30
34 description="""\
35 Takes two dictionary and compares them semantically (by looking at the
36 structure, not the textual representation. If the dictionaries do not
37 have the same name, it looks for the destination file by searching the
38 equivalent place in the destination case. If more than two files are
39 specified then the last name is assumed to be a directory and all the
40 equivalents to the other files are searched there.
41 """
42
43 PyFoamApplication.__init__(self,
44 args=args,
45 description=description,
46 usage="%prog [options] <source> <destination-case>",
47 nr=2,
48 exactNr=False,
49 interspersed=True)
50
52 self.parser.add_option("--not-equal",
53 action="store_true",
54 default=False,
55 dest="notequal",
56 help="Allow source and destination to have different names")
57 self.parser.add_option("--debug",
58 action="store_true",
59 default=False,
60 dest="debug",
61 help="Debug the comparing process")
62 self.parser.add_option("--long-field-threshold",
63 action="store",
64 type="int",
65 default=None,
66 dest="longlist",
67 help="Fields that are longer than this won't be parsed, but read into memory (and compared as strings)")
68
69 CommonParserOptions.addOptions(self)
70
71
72
74 sFiles=self.parser.getArgs()[0:-1]
75 dFile=path.abspath(self.parser.getArgs()[-1])
76
77 for s in sFiles:
78 sName=path.abspath(s)
79 dName=dFile
80
81 if len(s)>1:
82 print_(f.name+"Source file",sName,f.reset)
83 try:
84 source=ParsedParameterFile(sName,
85 backup=False,
86 debug=self.opts.debugParser,
87 listLengthUnparsed=self.opts.longlist,
88 noBody=self.opts.noBody,
89 noHeader=self.opts.noHeader,
90 boundaryDict=self.opts.boundaryDict,
91 listDict=self.opts.listDict,
92 listDictWithHeader=self.opts.listDictWithHeader)
93 except IOError:
94 e = sys.exc_info()[1]
95 self.warning("Problem with file",sName,":",e)
96 continue
97 except PyFoamParserError:
98 e = sys.exc_info()[1]
99 self.warning("Parser problem with",sName,":",e)
100 continue
101
102 found=False
103
104 if path.isfile(sName) and path.isfile(dName):
105 found=True
106
107 if not found and not self.opts.notequal and path.basename(sName)!=path.basename(dName):
108 parts=sName.split(path.sep)
109 for i in range(len(parts)):
110 tmp=path.join(*[dName]+parts[-(i+1):])
111
112 if path.exists(tmp):
113 found=True
114 dName=tmp
115 warning("Found",dName,"and using this")
116 break
117
118 if not found:
119 error("Could not find a file named",path.basename(sName),"in",dName)
120
121 if path.samefile(sName,dName):
122 error("Source",sName,"and destination",dName,"are the same")
123
124 try:
125 dest=ParsedParameterFile(dName,
126 backup=False,
127 debug=self.opts.debugParser,
128 listLengthUnparsed=self.opts.longlist,
129 noBody=self.opts.noBody,
130 noHeader=self.opts.noHeader,
131 boundaryDict=self.opts.boundaryDict,
132 listDict=self.opts.listDict,
133 listDictWithHeader=self.opts.listDictWithHeader)
134 except IOError:
135 e = sys.exc_info()[1]
136 self.error("Problem with file",dName,":",e)
137
138 self.pling=False
139
140 if not self.opts.boundaryDict and not self.opts.listDict and not self.opts.listDictWithHeader:
141 self.compareDict(source.content,dest.content,1,path.basename(sName))
142 else:
143 self.compareIterable(source.content,dest.content,1,path.basename(sName))
144
145 if not self.pling:
146 print_("\nNo differences found")
147
150
153
154 - def compare(self,src,dst,depth,name):
155 if type(src)!=type(dst):
156 print_(f.diff+">><<",name,": Types differ"+f.reset+"\n+"+f.src+">>Source:"+f.reset+"\n",makeString(src),"\n"+f.dst+"<<Destination:"+f.reset+"\n",makeString(dst)+f.reset)
157 self.pling=True
158 elif type(src) in [tuple,list,TupleProxy]:
159 self.compareIterable(src,dst,depth,name)
160 elif isinstance(src,(str,float)+integer_types) or src==None:
161 self.comparePrimitive(src,dst,depth,name)
162 elif src.__class__ in [Dimension,Tensor,SymmTensor,Vector]:
163 self.comparePrimitive(src,dst,depth,name)
164 elif src.__class__==Field:
165 self.compareField(src,dst,depth,name)
166 elif type(src) in [DictProxy,dict]:
167 self.compareDict(src,dst,depth,name)
168 else:
169 warning("Type of",name,"=",type(src),"unknown")
170 if self.opts.debug:
171 try:
172 print_("Class of",name,"=",src.__class__,"unknown")
173 except:
174 pass
175
177 if src!=dst:
178 self.pling=True
179 print_(f.diff+">><< Field",name,": Differs"+f.reset+"\n"+f.src+">>Source:"+f.reset+"\n",end=" ")
180 if src.uniform:
181 print_(src)
182 else:
183 print_("nonuniform - field not printed")
184 print_(f.dst+"<<Destination:"+f.reset+"\n",end=" ")
185 if dst.uniform:
186 print_(dst)
187 else:
188 print_("nonuniform - field not printed")
189
191 if src!=dst:
192 print_(f.diff+">><<",name,": Differs"+f.reset+"\n"+f.src+">>Source:"+f.reset+"\n",src,"\n"+f.dst+"<<Destination:"+f.reset+"\n",dst)
193 self.pling=True
194
196 nr=min(len(src),len(dst))
197
198 for i in range(nr):
199 if self.opts.debug:
200 print_("Comparing",self.iterString(name,i))
201 self.compare(src[i],dst[i],depth+1,self.iterString(name,i))
202
203 if nr<len(src):
204 print_(f.src+">>>>",self.iterString(name,nr),"to",self.iterString(name,len(src)-1),"missing from destination\n"+f.reset,makeString(src[nr:]))
205 self.pling=True
206 elif nr<len(dst):
207 print_(f.dst+"<<<<",self.iterString(name,nr),"to",self.iterString(name,len(dst)-1),"missing from source\n"+f.reset,makeString(dst[nr:]))
208 self.pling=True
209
211 for n in src:
212 if not n in dst:
213 print_(f.src+">>>>",self.dictString(name,n),": Missing from destination\n"+f.reset,makeString(src[n]))
214 self.pling=True
215 else:
216 if self.opts.debug:
217 print_("Comparing",self.dictString(name,n))
218 self.compare(src[n],dst[n],depth+1,self.dictString(name,n))
219
220 for n in dst:
221 if not n in src:
222 print_(f.dst+"<<<<",self.dictString(name,n),": Missing from source\n"+f.reset,makeString(dst[n]))
223 self.pling=True
224
225
226