bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
|
5340.4.2
by Gary van der Merwe
Add copy of boot_common.py for py2exe svn rev 688. |
1 |
# Common py2exe boot script - executed for all target types.
|
2 |
||
3 |
# When we are a windows_exe we have no console, and writing to
|
|
4 |
# sys.stderr or sys.stdout will sooner or later raise an exception,
|
|
5 |
# and tracebacks will be lost anyway (see explanation below).
|
|
6 |
#
|
|
7 |
# We assume that output to sys.stdout can go to the bitsink, but we
|
|
8 |
# *want* to see tracebacks. So we redirect sys.stdout into an object
|
|
9 |
# with a write method doing nothing, and sys.stderr into a logfile
|
|
10 |
# having the same name as the executable, with '.log' appended.
|
|
11 |
#
|
|
12 |
# We only open the logfile if something is written to sys.stderr.
|
|
13 |
#
|
|
14 |
# If the logfile cannot be opened for *any* reason, we have no choice
|
|
15 |
# but silently ignore the error.
|
|
16 |
#
|
|
17 |
# It remains to be seen if the 'a' flag for opening the logfile is a
|
|
18 |
# good choice, or 'w' would be better.
|
|
19 |
#
|
|
20 |
# More elaborate explanation on why this is needed:
|
|
21 |
#
|
|
22 |
# The sys.stdout and sys.stderr that GUI programs get (from Windows) are
|
|
23 |
# more than useless. This is not a py2exe problem, pythonw.exe behaves
|
|
24 |
# in the same way.
|
|
25 |
#
|
|
26 |
# To demonstrate, run this program with pythonw.exe:
|
|
27 |
#
|
|
28 |
# import sys
|
|
29 |
# sys.stderr = open("out.log", "w")
|
|
30 |
# for i in range(10000):
|
|
31 |
# print i
|
|
32 |
#
|
|
33 |
# and open the 'out.log' file. It contains this:
|
|
34 |
#
|
|
35 |
# Traceback (most recent call last):
|
|
36 |
# File "out.py", line 6, in ?
|
|
37 |
# print i
|
|
38 |
# IOError: [Errno 9] Bad file descriptor
|
|
39 |
#
|
|
40 |
# In other words, after printing a certain number of bytes to the
|
|
41 |
# system-supplied sys.stdout (or sys.stderr) an exception will be raised.
|
|
42 |
#
|
|
43 |
||
44 |
import sys |
|
45 |
if sys.frozen == "windows_exe": |
|
46 |
class Stderr(object): |
|
47 |
softspace = 0 |
|
48 |
_file = None |
|
49 |
_error = None |
|
50 |
def write(self, text, alert=sys._MessageBox, fname=sys.executable + '.log'): |
|
51 |
if self._file is None and self._error is None: |
|
52 |
try: |
|
53 |
self._file = open(fname, 'a') |
|
54 |
except Exception, details: |
|
55 |
self._error = details |
|
56 |
import atexit |
|
57 |
atexit.register(alert, 0, |
|
58 |
"The logfile '%s' could not be opened:\n %s" % \ |
|
59 |
(fname, details), |
|
60 |
"Errors occurred") |
|
61 |
else: |
|
62 |
import atexit |
|
63 |
atexit.register(alert, 0, |
|
64 |
"See the logfile '%s' for details" % fname, |
|
65 |
"Errors occurred") |
|
66 |
if self._file is not None: |
|
67 |
self._file.write(text) |
|
68 |
self._file.flush() |
|
69 |
def flush(self): |
|
70 |
if self._file is not None: |
|
71 |
self._file.flush() |
|
72 |
sys.stderr = Stderr() |
|
73 |
del sys._MessageBox |
|
74 |
del Stderr |
|
75 |
||
76 |
class Blackhole(object): |
|
77 |
softspace = 0 |
|
78 |
def write(self, text): |
|
79 |
pass
|
|
80 |
def flush(self): |
|
81 |
pass
|
|
82 |
sys.stdout = Blackhole() |
|
83 |
del Blackhole |
|
84 |
del sys |
|
85 |
||
86 |
# Disable linecache.getline() which is called by
|
|
87 |
# traceback.extract_stack() when an exception occurs to try and read
|
|
88 |
# the filenames embedded in the packaged python code. This is really
|
|
89 |
# annoying on windows when the d: or e: on our build box refers to
|
|
90 |
# someone elses removable or network drive so the getline() call
|
|
91 |
# causes it to ask them to insert a disk in that drive.
|
|
92 |
import linecache |
|
93 |
def fake_getline(filename, lineno, module_globals=None): |
|
94 |
return '' |
|
95 |
linecache.orig_getline = linecache.getline |
|
96 |
linecache.getline = fake_getline |
|
97 |
||
98 |
del linecache, fake_getline |