]>
Commit | Line | Data |
---|---|---|
1 | """ | |
2 | Convert modules from the old 'from wxPython.wx import *' style to | |
3 | the new 'import wx' style. | |
4 | ||
5 | Author: dfh@forestfield.co.uk (David Hughes) | |
6 | ||
7 | ||
8 | This should probably go in the tools package and have a startup script | |
9 | like the others, but I don't think it's ready for prime-time yet. So | |
10 | just put it in distrib for now so it doesn't get lost... | |
11 | ||
12 | --Robin | |
13 | """ | |
14 | ||
15 | ||
16 | import os, sys, time | |
17 | import string | |
18 | t0 = time.time() | |
19 | ||
20 | ||
21 | import wx | |
22 | print 'length = ', len(wx._newnames) | |
23 | ||
24 | for key in ['true', 'True', 'false', 'False']: # use native Python not wx.<bool> | |
25 | if key in wx._newnames: | |
26 | del wx._newnames[key] | |
27 | ||
28 | import wx.calendar, wx.gizmos, wx.glcanvas, wx.grid, wx.help, wx.html, \ | |
29 | wx.htmlhelp, wx.iewin, wx.ogl, wx.stc, wx.wizard, wx.xrc | |
30 | import wx.lib | |
31 | ##import wx.lib.activexwrapper, wx.lib.analogclock, wx.lib.anchors, \ | |
32 | import wx.lib.activexwrapper, wx.lib.anchors, \ | |
33 | wx.lib.buttons, wx.lib.calendar, wx.lib.ClickableHtmlWindow, \ | |
34 | wx.lib.colourdb, wx.lib.colourselect, wx.lib.dialogs, \ | |
35 | wx.lib.ErrorDialogs, wx.lib.evtmgr, wx.lib.fancytext, \ | |
36 | wx.lib.filebrowsebutton, wx.lib.gridmovers, wx.lib.grids, \ | |
37 | wx.lib.imagebrowser, wx.lib.imageutils, wx.lib.infoframe, \ | |
38 | wx.lib.intctrl, wx.lib.layoutf, wx.lib.multisash, \ | |
39 | wx.lib.popupctl, wx.lib.printout, wx.lib.rcsizer, \ | |
40 | wx.lib.rightalign, wx.lib.sheet, wx.lib.stattext, \ | |
41 | wx.lib.throbber, wx.lib.timectrl, wx.lib.wxPlotCanvas, \ | |
42 | wx.lib.wxpTag | |
43 | import wx.lib.mixins, wx.lib.editor, wx.lib.colourchooser | |
44 | import wx.lib.mixins.grid, wx.lib.mixins.imagelist, \ | |
45 | wx.lib.mixins.listctrl | |
46 | ## wx.lib.mixins.listctrl, wx.lib.mixins.rubberband | |
47 | import wx.lib.editor.editor, wx.lib.editor.images, wx.lib.editor.selection | |
48 | import wx.lib.colourchooser.canvas, wx.lib.colourchooser.intl, wx.lib.colourchooser.pycolourbox, \ | |
49 | wx.lib.colourchooser.pycolourchooser, wx.lib.colourchooser.pycolourslider, wx.lib.colourchooser.pypalette | |
50 | ||
51 | wxlist = [] | |
52 | for kd in wx._newnames.items(): | |
53 | wxlist.append(kd) | |
54 | wxlist.sort() | |
55 | ||
56 | n = 0 | |
57 | for item in wxlist: | |
58 | n += 1 | |
59 | ## print n, item | |
60 | print 'length = ', len(wx._newnames) | |
61 | print 'imports completed in ', time.time()-t0, 'secs' | |
62 | ||
63 | base_path = 'G:/wxConvert/Test1' | |
64 | exclude_dir = ( 'wx', 'wx_cc', 'reportlab', 'sqlite') # MUST exclude wx if it is below base_dir, others optional | |
65 | ||
66 | other_subs = { 'true': 'True', | |
67 | 'false': 'False' | |
68 | } | |
69 | ||
70 | punct = string.punctuation.replace('_','') # exclude single underscore | |
71 | punct = punct.replace('.','') # and period | |
72 | punct = punct.replace('*','') # and asterisk, all allowed in names | |
73 | punctable = string.maketrans(punct, ' '*len(punct)) # map punctuation characters to spaces | |
74 | numfiles = 0 | |
75 | ||
76 | #---------------------------------------------------------------------------- | |
77 | ||
78 | class AFile: | |
79 | " file object - collection of properties relating to current instance" | |
80 | def __init__(self, subsdict): | |
81 | self.subsdict = subsdict.copy() # dictionary of universal and local substitutions to make | |
82 | self.importing = [] # list of wx modules being imported | |
83 | ||
84 | #---------------------------------------------------------------------------- | |
85 | ||
86 | def visit(noargs, thispath, contentlist): | |
87 | """ Function is called by os walk for every directory in base_path, | |
88 | including base_path itself. Contentlist is a list of files/dirs in thispath. | |
89 | Wx conversion function is called for every qualifying file in list | |
90 | """ | |
91 | path = thispath | |
92 | base = 'something' | |
93 | while base: # check if thispath or a parent is excluded | |
94 | path, base = os.path.split(path) | |
95 | if base in exclude_dir: | |
96 | print 'Excluded:', thispath | |
97 | return | |
98 | ||
99 | for item in contentlist: | |
100 | pathname = os.path.join(thispath, item) | |
101 | if os.path.isfile(pathname) and pathname[-3:].lower() == '.py': | |
102 | wxconvert(pathname) | |
103 | ||
104 | def wxconvert(pathname): | |
105 | """ Scan each line of text in pathname. Replace each occurrence of any key in wx._newnames | |
106 | dictionary with the content stored under that key | |
107 | """ | |
108 | global numfiles | |
109 | afile = AFile(other_subs) | |
110 | infile = open(pathname, 'r') | |
111 | linelist = infile.readlines() | |
112 | infile.close() | |
113 | ||
114 | lnum = 0 | |
115 | outlist = [] | |
116 | for line in linelist: | |
117 | lnum += 1 | |
118 | tokenlist = line.replace('.__', ' ').translate(punctable).split() # split on white space and punctuation | |
119 | line, status = checkimports(afile, line, tokenlist) # return line with 'import' modifications | |
120 | if not status: | |
121 | print 'Unable to convert line %d in %s' % (lnum, pathname) | |
122 | break | |
123 | else: | |
124 | for key in afile.subsdict: # do other changes first | |
125 | if line.find(key) >= 0: | |
126 | line = line.replace(key, afile.subsdict[key]) | |
127 | for token in tokenlist: # change wx names | |
128 | if token in wx._newnames: | |
129 | candidate = wx._newnames[token] | |
130 | module = candidate[:candidate.rfind('.')] | |
131 | if module in afile.importing: | |
132 | line = line.replace(token, candidate) | |
133 | outlist.append(line) | |
134 | else: | |
135 | outfile = open(pathname, 'w') | |
136 | outfile.writelines(outlist) | |
137 | numfiles += 1 | |
138 | print 'Converted:', pathname | |
139 | outfile.close() | |
140 | ||
141 | def checkimports(afile, line, tlist): | |
142 | """ Scan tokenlist for wxPython import statement. Add to afile.subsdict any | |
143 | name changes that are necessary for the rest of the current source file. | |
144 | Add to afile.importing any new import modules | |
145 | Return a tuple (status, newstring) - | |
146 | line, possibly modified if an import statmeny | |
147 | status: 0: unable to handle complexity, 1: OK | |
148 | """ | |
149 | aline = line | |
150 | if len(tlist) == 0: return (aline, 1) | |
151 | indent = '' | |
152 | for ch in line: | |
153 | if ch in string.whitespace: | |
154 | indent += ' ' | |
155 | else: | |
156 | break | |
157 | ||
158 | if tlist[0] == 'import': # import module [as name] [module [as name]...] | |
159 | skip = False | |
160 | for t in tlist[1:]: | |
161 | if skip: | |
162 | skip = False | |
163 | elif t == 'as': | |
164 | skip = True | |
165 | elif t.startswith('wx'): | |
166 | aline = aline.replace(t, rename_module(afile, t)) | |
167 | elif (tlist[0] == 'from' and | |
168 | tlist[1] == 'wxPython' and | |
169 | tlist[2] == 'import'): # from wxPython import module | |
170 | if len(tlist) > 4: # ...[as name] [module [as name]...] | |
171 | return ('', 0) # too complicated | |
172 | module = rename_module(afile,tlist[-1]) | |
173 | aline = indent = 'import ' + module + '\n' | |
174 | elif (tlist[0] == 'from' and | |
175 | tlist[1].startswith('wxPython') and | |
176 | tlist[2] == 'import'): # from module import .... | |
177 | if tlist[-1] <> '*': # ...name [as name] [name [as name]...] | |
178 | aline = aline.replace(tlist[1], rename_module(afile, tlist[1])) | |
179 | skip = False | |
180 | for t in tlist[3:]: | |
181 | if skip: | |
182 | skip = False | |
183 | elif t == 'as': | |
184 | skip = True | |
185 | else: | |
186 | elem = t.split('.') | |
187 | if elem[-1].startswith('wx'): # remove wx prefix from last element of name | |
188 | elem[-1] = elem[-1][2:] | |
189 | afile.subsdict[t] = '.'.join(elem) # and apply to each occurrence in source | |
190 | else: # from module import * | |
191 | module = rename_module(afile,tlist[1]) | |
192 | aline = indent = 'import ' + module + '\n' | |
193 | return (aline, 1) | |
194 | ||
195 | def rename_module(afile, t, type='A'): | |
196 | """ Substitute wx for wxPython.wx or wx, and wx.foo.bar for wxPython.foo.bar in token | |
197 | foo.bar => wx.foo.bar is also permitted (from wxPython import foo.bar) | |
198 | """ | |
199 | if t in ['wx', 'wxPython.wx']: | |
200 | module = 'wx' | |
201 | elif t.startswith('wxPython'): | |
202 | module = t.replace('wxPython', 'wx') | |
203 | elif t.startswith('wx'): | |
204 | module = t | |
205 | else: | |
206 | module = 'wx.' + t | |
207 | if module not in afile.importing: | |
208 | afile.importing.append(module) | |
209 | return module | |
210 | ||
211 | def main(): | |
212 | " Convert every file in base_dir and all subdirectories except in exclude_dir list" | |
213 | ||
214 | os.path.walk(base_path, visit, None) | |
215 | print '%d files converted in %.2f seconds' % (numfiles, time.time() - t0) | |
216 | ||
217 | #---------------------------------------------------------------------------- | |
218 | ||
219 | if __name__ == '__main__': | |
220 | main() |