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 except IOError,e:
74 self.error("Problem with file",sName,":",e)
75
76 found=False
77
78 if path.isfile(sName) and path.isfile(dName):
79 found=True
80
81 if not found and not self.opts.notequal and path.basename(sName)!=path.basename(dName):
82 parts=sName.split(path.sep)
83 for i in range(len(parts)):
84 tmp=apply(path.join,[dName]+parts[-(i+1):])
85
86 if path.exists(tmp):
87 found=True
88 dName=tmp
89 warning("Found",dName,"and using this")
90 break
91
92 if not found:
93 error("Could not find a file named",path.basename(sName),"in",dName)
94
95 if path.samefile(sName,dName):
96 error("Source",sName,"and destination",dName,"are the same")
97
98 try:
99 dest=ParsedParameterFile(dName,
100 backup=False,
101 debug=self.opts.debugParser,
102 listLengthUnparsed=self.opts.longlist,
103 noBody=self.opts.noBody,
104 noHeader=self.opts.noHeader,
105 boundaryDict=self.opts.boundaryDict,
106 listDict=self.opts.listDict)
107 except IOError,e:
108 self.error("Problem with file",dName,":",e)
109
110 self.pling=False
111
112 if not self.opts.boundaryDict and not self.opts.listDict:
113 self.compareDict(source.content,dest.content,1,path.basename(sName))
114 else:
115 self.compareIterable(source.content,dest.content,1,path.basename(sName))
116
117 if not self.pling:
118 print "\nNo differences found"
119
121 return "%s[%s]" % (path,name)
122
124 return "%s[%d]" % (path,index)
125
126 - def compare(self,src,dst,depth,name):
127 if type(src)!=type(dst):
128 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
129 self.pling=True
130 elif type(src) in [tuple,list,TupleProxy]:
131 self.compareIterable(src,dst,depth,name)
132 elif type(src) in [str,float,int,long,type(None)]:
133 self.comparePrimitive(src,dst,depth,name)
134 elif src.__class__ in [Dimension,Tensor,SymmTensor,Vector]:
135 self.comparePrimitive(src,dst,depth,name)
136 elif src.__class__==Field:
137 self.compareField(src,dst,depth,name)
138 elif type(src) in [DictProxy,dict]:
139 self.compareDict(src,dst,depth,name)
140 else:
141 warning("Type of",name,"=",type(src),"unknown")
142 if self.opts.debug:
143 try:
144 print "Class of",name,"=",src.__class__,"unknown"
145 except:
146 pass
147
149 if src!=dst:
150 self.pling=True
151 print f.diff+">><< Field",name,": Differs"+f.reset+"\n"+f.src+">>Source:"+f.reset+"\n",
152 if src.uniform:
153 print src
154 else:
155 print "nonuniform - field not printed"
156 print f.dst+"<<Destination:"+f.reset+"\n",
157 if dst.uniform:
158 print dst
159 else:
160 print "nonuniform - field not printed"
161
163 if src!=dst:
164 print f.diff+">><<",name,": Differs"+f.reset+"\n"+f.src+">>Source:"+f.reset+"\n",src,"\n"+f.dst+"<<Destination:"+f.reset+"\n",dst
165 self.pling=True
166
168 nr=min(len(src),len(dst))
169
170 for i in range(nr):
171 if self.opts.debug:
172 print "Comparing",self.iterString(name,i)
173 self.compare(src[i],dst[i],depth+1,self.iterString(name,i))
174
175 if nr<len(src):
176 print f.src+">>>>",self.iterString(name,nr),"to",self.iterString(name,len(src)-1),"missing from destination\n"+f.reset,makeString(src[nr:])
177 self.pling=True
178 elif nr<len(dst):
179 print f.dst+"<<<<",self.iterString(name,nr),"to",self.iterString(name,len(dst)-1),"missing from source\n"+f.reset,makeString(dst[nr:])
180 self.pling=True
181
183 for n in src:
184 if not n in dst:
185 print f.src+">>>>",self.dictString(name,n),": Missing from destination\n"+f.reset,makeString(src[n])
186 self.pling=True
187 else:
188 if self.opts.debug:
189 print "Comparing",self.dictString(name,n)
190 self.compare(src[n],dst[n],depth+1,self.dictString(name,n))
191
192 for n in dst:
193 if not n in src:
194 print f.dst+"<<<<",self.dictString(name,n),": Missing from source\n"+f.reset,makeString(dst[n])
195 self.pling=True
196