1
2 """
3 Application class that implements pyFoamCompareDictionary.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,Dimension,Tensor,SymmTensor,Vector,Field,TupleProxy
13 from PyFoam.Basics.FoamFileGenerator import makeString
14
15 from PyFoam.Error import error,warning
16
17 from CommonParserOptions import CommonParserOptions
18
19 from PyFoam.Basics.TerminalFormatter import TerminalFormatter
20
21 f=TerminalFormatter()
22 f.getConfigFormat("source",shortName="src")
23 f.getConfigFormat("destination",shortName="dst")
24 f.getConfigFormat("difference",shortName="diff")
25
29 description="""
30 Takes two dictionary and compares them semantically (by looking at the
31 structure, not the textual representation. If the dictionaries do not
32 have the same name, it looks for the destination file by searching the
33 equivalent place in the destination case
34 """
35
36 PyFoamApplication.__init__(self,args=args,description=description,usage="%prog [options] <source> <destination-case>",nr=2,interspersed=True)
37
39 self.parser.add_option("--not-equal",
40 action="store_true",
41 default=False,
42 dest="notequal",
43 help="Allow source and destination to have different names")
44 self.parser.add_option("--debug",
45 action="store_true",
46 default=False,
47 dest="debug",
48 help="Debug the comparing process")
49 self.parser.add_option("--long-field-threshold",
50 action="store",
51 type="int",
52 default=None,
53 dest="longlist",
54 help="Fields that are longer than this won't be parsed, but read into memory (and compared as strings)")
55
56 CommonParserOptions.addOptions(self)
57
58
59
61 sName=path.abspath(self.parser.getArgs()[0])
62 dName=path.abspath(self.parser.getArgs()[1])
63
64 try:
65 source=ParsedParameterFile(sName,
66 backup=False,
67 debug=self.opts.debugParser,
68 listLengthUnparsed=self.opts.longlist,
69 noBody=self.opts.noBody,
70 noHeader=self.opts.noHeader,
71 boundaryDict=self.opts.boundaryDict,
72 listDict=self.opts.listDict,
73 listDictWithHeader=self.opts.listDictWithHeader)
74 except IOError,e:
75 self.error("Problem with file",sName,":",e)
76
77 found=False
78
79 if path.isfile(sName) and path.isfile(dName):
80 found=True
81
82 if not found and not self.opts.notequal and path.basename(sName)!=path.basename(dName):
83 parts=sName.split(path.sep)
84 for i in range(len(parts)):
85 tmp=apply(path.join,[dName]+parts[-(i+1):])
86
87 if path.exists(tmp):
88 found=True
89 dName=tmp
90 warning("Found",dName,"and using this")
91 break
92
93 if not found:
94 error("Could not find a file named",path.basename(sName),"in",dName)
95
96 if path.samefile(sName,dName):
97 error("Source",sName,"and destination",dName,"are the same")
98
99 try:
100 dest=ParsedParameterFile(dName,
101 backup=False,
102 debug=self.opts.debugParser,
103 listLengthUnparsed=self.opts.longlist,
104 noBody=self.opts.noBody,
105 noHeader=self.opts.noHeader,
106 boundaryDict=self.opts.boundaryDict,
107 listDict=self.opts.listDict,
108 listDictWithHeader=self.opts.listDictWithHeader)
109 except IOError,e:
110 self.error("Problem with file",dName,":",e)
111
112 self.pling=False
113
114 if not self.opts.boundaryDict and not self.opts.listDict and not self.opts.listDictWithHeader:
115 self.compareDict(source.content,dest.content,1,path.basename(sName))
116 else:
117 self.compareIterable(source.content,dest.content,1,path.basename(sName))
118
119 if not self.pling:
120 print "\nNo differences found"
121
123 return "%s[%s]" % (path,name)
124
126 return "%s[%d]" % (path,index)
127
128 - def compare(self,src,dst,depth,name):
129 if type(src)!=type(dst):
130 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
131 self.pling=True
132 elif type(src) in [tuple,list,TupleProxy]:
133 self.compareIterable(src,dst,depth,name)
134 elif type(src) in [str,float,int,long,type(None)]:
135 self.comparePrimitive(src,dst,depth,name)
136 elif src.__class__ in [Dimension,Tensor,SymmTensor,Vector]:
137 self.comparePrimitive(src,dst,depth,name)
138 elif src.__class__==Field:
139 self.compareField(src,dst,depth,name)
140 elif type(src) in [DictProxy,dict]:
141 self.compareDict(src,dst,depth,name)
142 else:
143 warning("Type of",name,"=",type(src),"unknown")
144 if self.opts.debug:
145 try:
146 print "Class of",name,"=",src.__class__,"unknown"
147 except:
148 pass
149
151 if src!=dst:
152 self.pling=True
153 print f.diff+">><< Field",name,": Differs"+f.reset+"\n"+f.src+">>Source:"+f.reset+"\n",
154 if src.uniform:
155 print src
156 else:
157 print "nonuniform - field not printed"
158 print f.dst+"<<Destination:"+f.reset+"\n",
159 if dst.uniform:
160 print dst
161 else:
162 print "nonuniform - field not printed"
163
165 if src!=dst:
166 print f.diff+">><<",name,": Differs"+f.reset+"\n"+f.src+">>Source:"+f.reset+"\n",src,"\n"+f.dst+"<<Destination:"+f.reset+"\n",dst
167 self.pling=True
168
170 nr=min(len(src),len(dst))
171
172 for i in range(nr):
173 if self.opts.debug:
174 print "Comparing",self.iterString(name,i)
175 self.compare(src[i],dst[i],depth+1,self.iterString(name,i))
176
177 if nr<len(src):
178 print f.src+">>>>",self.iterString(name,nr),"to",self.iterString(name,len(src)-1),"missing from destination\n"+f.reset,makeString(src[nr:])
179 self.pling=True
180 elif nr<len(dst):
181 print f.dst+"<<<<",self.iterString(name,nr),"to",self.iterString(name,len(dst)-1),"missing from source\n"+f.reset,makeString(dst[nr:])
182 self.pling=True
183
185 for n in src:
186 if not n in dst:
187 print f.src+">>>>",self.dictString(name,n),": Missing from destination\n"+f.reset,makeString(src[n])
188 self.pling=True
189 else:
190 if self.opts.debug:
191 print "Comparing",self.dictString(name,n)
192 self.compare(src[n],dst[n],depth+1,self.dictString(name,n))
193
194 for n in dst:
195 if not n in src:
196 print f.dst+"<<<<",self.dictString(name,n),": Missing from source\n"+f.reset,makeString(dst[n])
197 self.pling=True
198