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)