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