forked from lballabio/quantlib-old
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfind_replace.py
More file actions
277 lines (238 loc) · 7.51 KB
/
Copy pathfind_replace.py
File metadata and controls
277 lines (238 loc) · 7.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
##################################################################################
#
# find_replace.py - perform a recursive find/replace on a directory tree
#
# To use this script, first edit it as required (see below) then invoke
# as follows:
#
# find_replace.py -[mode]
# Where [mode] is either of:
# d - display proposed substitutions
# s - perform the substitutions
# Plus optionally
# v - verbose
#
# Settings within this script:
#
# ROOT_DIRS
# The list of root folders from which you want the find/replace to begin.
#
# SUBSTITUTIONS
# A list of one or more regexes to be performed on each file.
#
# INCLUDE_FILES
# Regexes to indicate names of files to be processed by the find/replace.
#
# IGNORE_FILES
# Regexes to indicate names of files to be ignored by the find/replace.
# NB the script tests first whether the file is to be ignored, then whether it
# is to be included.
#
# IGNORE_DIRS
# Regexes to indicate directories to be ignored by the find/replace.
#
##################################################################################
import sys
import os
import re
import getopt
import shutil
# ROOT_DIRS - The list of root folders from which
# you want the find/replace to begin.
ROOT_DIRS = (
#'C:/erik/ql/R01020x-branch/log4cxx',
'/media/windows/linux/repos/quantlib/gensrc',
'/media/windows/linux/repos/quantlib/ObjectHandler',
'/media/windows/linux/repos/quantlib/QuantLibAddin',
'/media/windows/linux/repos/quantlib/QuantLibXL'
)
# CALLBACK FUNCTIONS - Called from regexes which require multiple passes
# Convert case
def toLower(m): return m.group(0).lower()
# Replace pre increment/decrement with post increment/decrement
regex1 = re.compile(r'(\w+?)\+\+')
regex2 = re.compile(r'(\w+?)--')
def callback_example(m):
x = regex1.sub('++\1', m.group(2))
x = regex2.sub('--\1', x)
return m.group(1) + x + ')'
# SUBSTITUTIONS - A list of regexes to be performed.
# Each substitution is in the format
# (re.compile('find text'), 'replace text'),
SUBSTITUTIONS = (
## Uncomment and modify the examples as required.
## 1) Simple
## Straight find/replace.
# (re.compile('aaa'), 'bbb'),
## 2) Group
## Use parentheses to indicate group(s) in the find text.
## Use \x in the replace text to refer to a group, where x = group number.
## Replace text must be a raw string r'' instead of normal string ''.
# (re.compile('ccc(.*)ccc'), r'ddd\1ddd'),
## 3) Newline flag
## Use re.S to indicate that . matches newline.
## This allows you to perform substitutions that span lines.
# (re.compile('eee.*eee', re.S), 'fff'),
## 4) Multiline flag
## Use re.M to anchor ^ and $ to begin/end of lines within buffer.
# (re.compile('^ggg.*ggg$', re.M | re.S), 'hhh'),
## 5) Conversion function
## Instead of replacement text, provide name of conversion function.
# (re.compile('abcDEFghi'), toLower),
## Frequently used
(re.compile('1_4_0'), '1_5_0'),
(re.compile('1\.4\.0'), '1.5.0'),
(re.compile('0x010400'), '0x010500'),
(re.compile('R010401f0'), 'R010500f0'),
(re.compile('0\.10\.0d'), '0.10.0e'),
)
# INCLUDE_FILES
# Regexes to indicate names of files to be processed by the find/replace.
# Leave this list empty to process all files in the directory tree
# except for those excluded by IGNORE_FILES.
INCLUDE_FILES = (
# re.compile(r'^.+\.[ch]pp$'),
)
# IGNORE_FILES
# Regexes to indicate names of files to be ignored by the find/replace.
IGNORE_FILES = (
re.compile('^.+\.bmp$'),
re.compile('^.+\.exe$'),
re.compile('^.+\.exp$'),
re.compile('^.+\.ico$'),
re.compile('^.+\.jpg$'),
re.compile('^.+\.la$'),
re.compile('^.+\.lib$'),
re.compile('^.+\.log$'),
re.compile('^.+\.ncb$'),
re.compile('^.+\.o$'),
re.compile('^.+\.pdf$'),
re.compile('^.+\.plg$'),
re.compile('^.+\.png$'),
re.compile('^.+\.pyc$'),
re.compile('^.+\.xls$'),
re.compile('^.+~$'),
re.compile('^\.'),
re.compile('^Announce\.txt$'),
re.compile('^ChangeLog\.txt$'),
re.compile('^changes\..+$'),
re.compile('^config\.status$'),
re.compile('^configure$'),
re.compile('^design\.docs$'),
re.compile('^history\.docs$'),
re.compile('^libtool$'),
re.compile('^Makefile$'),
re.compile('^Makefile\.in$'),
re.compile('^NEWS\.txt$'),
re.compile('^News\.txt$'),
re.compile('^objecthandler\.cpp$'),
re.compile('^ohfunctions\.cpp$'),
re.compile('^todonando\.txt$'),
)
# IGNORE_DIRS
# Regexes to indicate directories to be ignored by the find/replace.
IGNORE_DIRS = (
re.compile('^\.'),
re.compile('^\.svn$'),
re.compile('^autom4te\.cache$'),
re.compile('^build$'),
re.compile('^configure$'),
re.compile('^dev_tools$'),
re.compile('^framework$'),
re.compile('^html$'),
re.compile('^Launcher$'),
re.compile('^lib$'),
re.compile('^log4cxx$'),
re.compile('^QuantLib$'),
re.compile('^QuantLib-site$'),
re.compile('^QuantLib-SWIG$'),
re.compile('^Workbooks$'),
)
def prompt_exit(msg='', status=0):
if msg:
print msg
#if sys.platform == 'win32':
# raw_input('press any key to exit')
sys.exit(status)
def usage():
prompt_exit('usage: ' + sys.argv[0] + ' -[mode]' + '''
where [mode] is either of:
d - display proposed substitutions
s - perform the substitutions
plus optionally
v - verbose
''')
def logMessage(msg, priority = 1):
global logLevel
if priority <= logLevel:
print msg
def ignoreItem(item, ignoreList):
for r in ignoreList:
if r.match(item):
return True
def includeItem(item, includeList):
if len(includeList) == 0: return True
for r in includeList:
if r.match(item):
return True
def processFile(fullPath):
global execSub
f = open(fullPath, 'r')
buf = f.read()
bufNew = buf
for sub in SUBSTITUTIONS:
r, repl = sub
bufNew = r.sub(repl, bufNew)
if bufNew == buf:
logMessage('no sub required in file ' + fullPath)
else:
if execSub:
logMessage('*** overwriting file ' + fullPath, 0)
f = open(fullPath, 'w')
f.write(bufNew)
else:
logMessage('*** sub required in file ' + fullPath, 0)
def processDir(ignore, dirPath, nameList):
i = len(nameList) - 1
while i > -1:
name = nameList[i]
fullPath = os.path.join(dirPath, name).replace('\\', '/')
logMessage('processing path ' + fullPath)
if os.path.isdir(fullPath):
logMessage('dir')
if ignoreItem(name, IGNORE_DIRS):
logMessage('ignoring directory ' + fullPath)
del nameList[i]
elif os.path.isfile(fullPath):
if ignoreItem(name, IGNORE_FILES):
logMessage('ignoring file ' + fullPath)
del nameList[i]
else:
logMessage('testing filename ' + name)
if includeItem(name, INCLUDE_FILES):
processFile(fullPath)
else:
prompt_exit('unknown file type: ' + fullPath)
i -= 1
try:
opts, args = getopt.getopt(sys.argv[1:], 'dsvh', 'help' )
except getopt.GetoptError:
usage()
logLevel = 0
execSub = -1
for o, a in opts:
if o in ('-h', '--help'):
usage()
elif o == '-d':
execSub = 0
elif o == '-s':
execSub = 1
elif o == '-v':
logLevel = 1
if execSub == -1:
usage()
for rootDir in ROOT_DIRS:
if not os.path.isdir(rootDir):
prompt_exit('invalid directory: ' + rootDir)
os.path.walk(rootDir, processDir, None)
prompt_exit()