1
"""Post-install GUI to compile to pyc and unpack twisted doco"""
3
from __future__ import generators
9
# we're going to ignore failures to import tkinter and fall back
10
# to using the console if the required dll is not found
12
# Scary kludge to work around tk84.dll bug:
13
# https://sourceforge.net/tracker/index.php?func=detail&aid=814654&group_id=5470&atid=105470
14
# Without which(): you get a windows missing-dll popup message
15
from twisted.python.procutils import which
17
if which(tkdll) or which('DLLs/%s' % tkdll):
21
from twisted.internet import tksupport
26
from twisted.internet import reactor, defer
27
from twisted.python import failure, log, zipstream, util, usage, log
32
def __init__(self, master=None, orientation="horizontal",
33
min=0, max=100, width=100, height=18,
34
doLabel=1, appearance="sunken",
35
fillColor="blue", background="gray",
36
labelColor="yellow", labelFont="Arial",
37
labelText="", labelFormat="%d%%",
39
# preserve various values
41
self.orientation=orientation
47
self.fillColor=fillColor
48
self.labelFont= labelFont
49
self.labelColor=labelColor
50
self.background=background
51
self.labelText=labelText
52
self.labelFormat=labelFormat
54
self.frame=Frame(master, relief=appearance, bd=bd)
55
self.canvas=Canvas(self.frame, height=height, width=width, bd=0,
56
highlightthickness=0, background=background)
57
self.scale=self.canvas.create_rectangle(0, 0, width, height,
59
self.label=self.canvas.create_text(self.canvas.winfo_reqwidth() / 2,
60
height / 2, text=labelText,
61
anchor="c", fill=labelColor,
64
self.canvas.pack(side='top', fill='x', expand='no')
66
def pack(self, *args, **kwargs):
67
self.frame.pack(*args, **kwargs)
69
def updateProgress(self, newValue, newMax=None):
76
# Trim the values to be between min and max
82
# Adjust the rectangle
83
if self.orientation == "horizontal":
84
self.canvas.coords(self.scale, 0, 0,
85
float(value) / self.max * self.width, self.height)
87
self.canvas.coords(self.scale, 0,
88
self.height - (float(value) /
89
self.max*self.height),
90
self.width, self.height)
91
# Now update the colors
92
self.canvas.itemconfig(self.scale, fill=self.fillColor)
93
self.canvas.itemconfig(self.label, fill=self.labelColor)
94
# And update the label
98
pvalue = int((float(value) / float(self.max)) *
102
self.canvas.itemconfig(self.label, text=self.labelFormat
105
self.canvas.itemconfig(self.label, text='')
107
self.canvas.itemconfig(self.label, text=self.labelFormat %
109
self.canvas.update_idletasks()
113
"""A base class to make it simple to hook a progress bar up to a process.
115
def __init__(self, title, *args, **kwargs):
122
def setBar(self, bar, max):
124
bar.updateProgress(0, max)
127
def setIterator(self, iterator):
128
self.iterator=iterator
131
def updateBar(self, deferred):
134
b.updateProgress(b.max - self.remaining)
138
deferred.errback(failure.Failure())
140
def processAll(self, root):
141
assert self.bar and self.iterator, "must setBar and setIterator"
143
root.title(self.title)
145
d.addErrback(log.err)
146
reactor.callLater(0.1, self.processOne, d)
149
def processOne(self, deferred):
151
deferred.callback(self.root)
155
self.remaining=self.iterator.next()
156
except StopIteration:
159
deferred.errback(failure.Failure())
161
if self.remaining%10==0:
162
reactor.callLater(0, self.updateBar, deferred)
163
if self.remaining%100==0:
164
log.msg(self.remaining)
165
reactor.callLater(0, self.processOne, deferred)
168
"""A generator for compiling files to .pyc"""
169
def justlist(arg, directory, names):
170
pynames=[os.path.join(directory, n) for n in names
171
if n.endswith('.py')]
174
os.path.walk(path, justlist, all)
177
i=zip(all, range(remaining-1, -1, -1))
178
for f, remaining in i:
179
py_compile.compile(f)
182
class TkunzipOptions(usage.Options):
183
optParameters=[["zipfile", "z", "", "a zipfile"],
184
["ziptargetdir", "t", ".", "where to extract zipfile"],
185
["compiledir", "c", "", "a directory to compile"],
187
optFlags=[["use-console", "C", "show in the console, not graphically"],
188
["shell-exec", "x", """\
189
spawn a new console to show output (implies -C)"""],
192
def countPys(countl, directory, names):
194
sofar=sofar+len([f for f in names if f.endswith('.py')])
198
def countPysRecursive(path):
200
os.path.walk(path, countPys, countl)
203
def run(argv=sys.argv):
204
log.startLogging(file('tkunzip.log', 'w'))
207
opt.parseOptions(argv[1:])
208
except usage.UsageError, e:
213
if opt['use-console']:
214
# this should come before shell-exec to prevent infinite loop
215
return doItConsolicious(opt)
216
if opt['shell-exec'] or not 'Tkinter' in sys.modules:
217
from distutils import sysconfig
218
from twisted.scripts import tkunzip
219
myfile=tkunzip.__file__
220
exe=os.path.join(sysconfig.get_config_var('prefix'), 'python.exe')
221
return os.system('%s %s --use-console %s' % (exe, myfile,
223
return doItTkinterly(opt)
225
def doItConsolicious(opt):
226
# reclaim stdout/stderr from log
227
sys.stdout = sys.__stdout__
228
sys.stderr = sys.__stderr__
230
print 'Unpacking documentation...'
231
for n in zipstream.unzipIter(opt['zipfile'], opt['ziptargetdir']):
236
print 'Done unpacking.'
238
if opt['compiledir']:
239
print 'Compiling to pyc...'
241
compileall.compile_dir(opt["compiledir"])
242
print 'Done compiling.'
244
def doItTkinterly(opt):
247
root.title('One Moment.')
248
root.protocol('WM_DELETE_WINDOW', reactor.stop)
249
tksupport.install(root)
251
prog=ProgressBar(root, value=0, labelColor="black", width=200)
254
# callback immediately
255
d=defer.succeed(root).addErrback(log.err)
261
d.addCallback(deiconify)
264
uz=Progressor('Unpacking documentation...')
265
max=zipstream.countZipFileChunks(opt['zipfile'], 4096)
267
uz.setIterator(zipstream.unzipIterChunky(opt['zipfile'],
268
opt['ziptargetdir']))
269
d.addCallback(uz.processAll)
271
if opt['compiledir']:
272
comp=Progressor('Compiling to pyc...')
273
comp.setBar(prog, countPysRecursive(opt['compiledir']))
274
comp.setIterator(compiler(opt['compiledir']))
275
d.addCallback(comp.processAll)
285
if __name__=='__main__':