| 
							- #!/usr/bin/env python
 - # encoding: utf-8
 - # Thomas Nagy, 2013 (ita)
 - 
 - """
 - A system for recording all outputs to a log file. Just add the following to your wscript file::
 - 
 -   def init(ctx):
 -     ctx.load('build_logs')
 - """
 - 
 - import atexit, sys, time, os, shutil, threading
 - from waflib import ansiterm, Logs, Context
 - 
 - # adding the logs under the build/ directory will clash with the clean/ command
 - try:
 - 	up = os.path.dirname(Context.g_module.__file__)
 - except AttributeError:
 - 	up = '.'
 - LOGFILE = os.path.join(up, 'logs', '%s.log' % time.strftime('%Y_%m_%d_%H_%M'))
 - 
 - wlock = threading.Lock()
 - class log_to_file(object):
 - 	def __init__(self, stream, fileobj, filename):
 - 		self.stream = stream
 - 		self.encoding = self.stream.encoding
 - 		self.fileobj = fileobj
 - 		self.filename = filename
 - 		self.is_valid = True
 - 	def replace_colors(self, data):
 - 		for x in Logs.colors_lst.values(): 
 - 			if isinstance(x, str):
 - 				data = data.replace(x, '')
 - 		return data
 - 	def write(self, data):
 - 		try:
 - 			wlock.acquire()
 - 			self.stream.write(data)
 - 			self.stream.flush()
 - 			if self.is_valid:
 - 				self.fileobj.write(self.replace_colors(data))
 - 		finally:
 - 			wlock.release()
 - 	def fileno(self):
 - 		return self.stream.fileno()
 - 	def flush(self):
 - 		self.stream.flush()
 - 		if self.is_valid:
 - 			self.fileobj.flush()
 - 	def isatty(self):
 - 		return self.stream.isatty()
 - 
 - def init(ctx):
 - 	global LOGFILE
 - 	filename = os.path.abspath(LOGFILE)
 - 	try:
 - 		os.makedirs(os.path.dirname(os.path.abspath(filename)))
 - 	except OSError:
 - 		pass
 - 
 - 	if hasattr(os, 'O_NOINHERIT'):
 - 		fd = os.open(LOGFILE, os.O_CREAT | os.O_TRUNC | os.O_WRONLY | os.O_NOINHERIT)
 - 		fileobj = os.fdopen(fd, 'w')
 - 	else:
 - 		fileobj = open(LOGFILE, 'w')
 - 	old_stderr = sys.stderr
 - 
 - 	# sys.stdout has already been replaced, so __stdout__ will be faster
 - 	#sys.stdout = log_to_file(sys.stdout, fileobj, filename)
 - 	#sys.stderr = log_to_file(sys.stderr, fileobj, filename)
 - 	def wrap(stream):
 - 		if stream.isatty():
 - 			return ansiterm.AnsiTerm(stream)
 - 		return stream
 - 	sys.stdout = log_to_file(wrap(sys.__stdout__), fileobj, filename)
 - 	sys.stderr = log_to_file(wrap(sys.__stderr__), fileobj, filename)
 - 
 - 	# now mess with the logging module...
 - 	for x in Logs.log.handlers:
 - 		try:
 - 			stream = x.stream
 - 		except AttributeError:
 - 			pass
 - 		else:
 - 			if id(stream) == id(old_stderr):
 - 				x.stream = sys.stderr
 - 
 - def exit_cleanup():
 - 	try:
 - 		fileobj = sys.stdout.fileobj
 - 	except AttributeError:
 - 		pass
 - 	else:
 - 		sys.stdout.is_valid = False
 - 		sys.stderr.is_valid = False
 - 		fileobj.close()
 - 		filename = sys.stdout.filename
 - 
 - 		Logs.info('Output logged to %r' % filename)
 - 
 - 		# then copy the log file to "latest.log" if possible
 - 		up = os.path.dirname(os.path.abspath(filename))
 - 		try:
 - 			shutil.copy(filename, os.path.join(up, 'latest.log'))
 - 		except OSError:
 - 			# this may fail on windows due to processes spawned
 - 			# 
 - 			pass
 - 
 - atexit.register(exit_cleanup)
 
 
  |