1## 2## This script recursively goes through the matlab directory and its 3## subdirectories in the unstable branch, comparing the calling structures of the 4## functions to those in another branch/commit, in this case the 4.2.5 branch 5## The output is compatible with a Dynare Wiki page 6## 7## NB: To err on the side of safety, this script won't clean your workspace so a 8## git command to checkout a different branch will fail if your workspace is 9## dirty. 10## 11 12## 13## Copyright © 2012 Dynare Team 14## 15## This file is part of Dynare. 16## 17## Dynare is free software: you can redistribute it and/or modify 18## it under the terms of the GNU General Public License as published by 19## the Free Software Foundation, either version 3 of the License, or 20## (at your option) any later version. 21## 22## Dynare is distributed in the hope that it will be useful, 23## but WITHOUT ANY WARRANTY; without even the implied warranty of 24## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25## GNU General Public License for more details. 26## 27## You should have received a copy of the GNU General Public License 28## along with Dynare. If not, see <http://www.gnu.org/licenses/>. 29## 30 31import os 32import string 33import subprocess 34import sys 35 36def runCompare(): 37 unstable = getFuncDict() 38 subprocess.call(['git','checkout','4.2']) 39 40 stable = getFuncDict() 41 subprocess.call(['git','checkout','master']) 42 43 us = set(unstable.keys()) 44 ss = set(stable.keys()) 45 46 deletedFunctions = sorted(ss - us) 47 makeOldFunctionsWikiTable(deletedFunctions, stable) 48 49 newFunctions = sorted(us - ss) 50 makeNewFunctionsWikiTable(newFunctions, unstable) 51 52 outputChanged = set([]) 53 inputChanged = set([]) 54 commonFunctions = sorted(ss & us) 55 for le in commonFunctions: 56 sOut = set(stable[le]['output']) 57 uOut = set(unstable[le]['output']) 58 sIn = set(stable[le]['input']) 59 uIn = set(unstable[le]['input']) 60 61 if len(uOut - sOut): 62 outputChanged.add(le) 63 64 if len(uIn - sIn): 65 inputChanged.add(le) 66 67 unionChanged = sorted(outputChanged | inputChanged) 68 makeUnionChangedWikiTable(unionChanged, stable, unstable) 69 70 71def makeUnionChangedWikiTable(keys, stable, unstable): 72 write = sys.stdout.write 73 print "= Functions Whose Arguments Have Changed between Dynare 4.2.5 and " \ 74 "Dynare 4.3 =" 75 print "|| '''Location''' || '''Old Output''' || " \ 76 "'''New Output''' || '''Old Input''' || '''New Input''' ||" 77 for k in keys: 78 write('|| {{{' + unstable[k]['filename'][10:] + '}}} || ') 79 write(str(stable[k]['output']) + ' || ') 80 write(str(unstable[k]['output']) + ' || ') 81 write(str(stable[k]['input']) + ' || ') 82 write(str(unstable[k]['input']) + ' ||') 83 print 84 85 86def makeNewFunctionsWikiTable(keys, dictionary): 87 print '= New Functions in Dynare 4.3 =' 88 makeWikiTable(keys, dictionary) 89 90 91def makeOldFunctionsWikiTable(keys, dictionary): 92 print '= Functions Removed in Dynare 4.3 =' 93 makeWikiTable(keys, dictionary) 94 95 96def makeWikiTable(keys, dictionary): 97 write = sys.stdout.write 98 print "|| '''Location''' || '''Output''' || '''Input''' ||" 99 for k in keys: 100 write('|| {{{' + dictionary[k]['filename'][10:] + '}}} || ') 101 write(str(dictionary[k]['output']) + ' || ') 102 write(str(dictionary[k]['input']) + ' ||') 103 print 104 105 106def printDict(dictionary, title): 107 print 108 print '***********************************' 109 print '** ' + title 110 print '***********************************' 111 for key in sorted(dictionary.iterkeys()): 112 b = dictionary[key] 113 print key + ':' + b['filename'] 114 print '***********************************' 115 print '***********************************' 116 print 117 118 119def getFuncDict(): 120 functions = {} 121 122 for dirname, dirnames, filenames in os.walk('../matlab'): 123 for filename in filenames: 124 filename = string.strip(filename) 125 126 if filename[-2:] != '.m' or filename == 'msstart2.m' or filename == 'msstart_setup.m' or filename == 'qmc_sequence.m': 127 continue 128 129 fullfilename = os.path.join(dirname, filename) 130 f = open(fullfilename, 'r') 131 funcDef = '' 132 inComment = False 133 while True: 134 funcDef += f.read(1) 135 if inComment: 136 if funcDef[-1:] == '\n': 137 inComment = False 138 else: 139 if funcDef[-1:] == '%': 140 inComment = True 141 elif funcDef[-1:] == ')': 142 break 143 funcDef = funcDef.strip() 144 f.close() 145 146 funcDict = {} 147 funcDict['filename'] = fullfilename 148 149 # OUTPUT 150 spliteq = string.rsplit(funcDef, '=') 151 if len(spliteq) == 1: 152 # no output 153 outputs = [''] 154 funcDict['output'] = outputs 155 rhs = string.split(funcDef, ' ', 1).pop(1).strip() 156 else: 157 outputs = string.split(spliteq.pop(0), ' ', 1).pop(1) 158 outputs = [string.strip(outputs, '[] ')] 159 outputs = getputs(outputs) 160 funcDict['output'] = outputs 161 rhs = string.strip(spliteq.pop(0), ' .\n') 162 163 # FUNCTION NAME 164 splitfn = string.split(rhs, '(') 165 fn = splitfn.pop(0) 166 167 # INPUT 168 inputs = [string.strip(le,')') for le in splitfn] 169 inputs = getputs(inputs) 170 funcDict['input'] = inputs 171 172 functions[fn] = funcDict 173 174 return functions 175 176 177def getputs(puts): 178 ''' Can be of the forms 179 a 180 a 181 a, b 182 a, b % aoeu 183 a, ... 184 b 185 a, ... % aoeu 186 b 187 188 Return a list of (in/out puts) 189 ''' 190 splitout = string.split(string.join(puts), '\n') 191 192 for i,le in enumerate(splitout[:]): 193 indx = string.find(le, '%') 194 if indx != -1: 195 splitout[i] = string.strip(le[:indx], '\t .') 196 else: 197 splitout[i] = string.strip(le, '\t .') 198 199 splitcommas = string.split(string.join(splitout), ',') 200 return [string.strip(le) for le in splitcommas] 201 202 203if __name__ == "__main__": 204 runCompare() 205