3 # Thomas Nagy, 2013 (ita)
6 A system for recording all outputs to a log file. Just add the following to your wscript file::
12 import atexit
, sys
, time
, os
, shutil
, threading
13 from waflib
import ansiterm
, Logs
, Context
15 # adding the logs under the build/ directory will clash with the clean/ command
17 up
= os
.path
.dirname(Context
.g_module
.__file
__)
18 except AttributeError:
20 LOGFILE
= os
.path
.join(up
, 'logs', time
.strftime('%Y_%m_%d_%H_%M.log'))
22 wlock
= threading
.Lock()
23 class log_to_file(object):
24 def __init__(self
, stream
, fileobj
, filename
):
26 self
.encoding
= self
.stream
.encoding
27 self
.fileobj
= fileobj
28 self
.filename
= filename
30 def replace_colors(self
, data
):
31 for x
in Logs
.colors_lst
.values():
32 if isinstance(x
, str):
33 data
= data
.replace(x
, '')
35 def write(self
, data
):
38 self
.stream
.write(data
)
41 self
.fileobj
.write(self
.replace_colors(data
))
45 return self
.stream
.fileno()
51 return self
.stream
.isatty()
55 filename
= os
.path
.abspath(LOGFILE
)
57 os
.makedirs(os
.path
.dirname(os
.path
.abspath(filename
)))
61 if hasattr(os
, 'O_NOINHERIT'):
62 fd
= os
.open(LOGFILE
, os
.O_CREAT | os
.O_TRUNC | os
.O_WRONLY | os
.O_NOINHERIT
)
63 fileobj
= os
.fdopen(fd
, 'w')
65 fileobj
= open(LOGFILE
, 'w')
66 old_stderr
= sys
.stderr
68 # sys.stdout has already been replaced, so __stdout__ will be faster
69 #sys.stdout = log_to_file(sys.stdout, fileobj, filename)
70 #sys.stderr = log_to_file(sys.stderr, fileobj, filename)
73 return ansiterm
.AnsiTerm(stream
)
75 sys
.stdout
= log_to_file(wrap(sys
.__stdout
__), fileobj
, filename
)
76 sys
.stderr
= log_to_file(wrap(sys
.__stderr
__), fileobj
, filename
)
78 # now mess with the logging module...
79 for x
in Logs
.log
.handlers
:
82 except AttributeError:
85 if id(stream
) == id(old_stderr
):
90 fileobj
= sys
.stdout
.fileobj
91 except AttributeError:
94 sys
.stdout
.is_valid
= False
95 sys
.stderr
.is_valid
= False
97 filename
= sys
.stdout
.filename
99 Logs
.info('Output logged to %r', filename
)
101 # then copy the log file to "latest.log" if possible
102 up
= os
.path
.dirname(os
.path
.abspath(filename
))
104 shutil
.copy(filename
, os
.path
.join(up
, 'latest.log'))
106 # this may fail on windows due to processes spawned
109 atexit
.register(exit_cleanup
)