Revision: 6431
Author: russblau
Date: 2009-02-23 19:19:09 +0000 (Mon, 23 Feb 2009)
Log Message:
-----------
Put colorization code in the logging handler, where it belongs, instead of colorizing records that aren't meant to be displayed on a terminal.
Modified Paths:
--------------
branches/rewrite/pywikibot/bot.py
branches/rewrite/pywikibot/userinterfaces/terminal_interface.py
Modified: branches/rewrite/pywikibot/bot.py
===================================================================
--- branches/rewrite/pywikibot/bot.py 2009-02-23 15:14:27 UTC (rev 6430)
+++ branches/rewrite/pywikibot/bot.py 2009-02-23 19:19:09 UTC (rev 6431)
@@ -48,69 +48,21 @@
return True
-class TerminalHandler(logging.Handler):
- """
- A handler class that writes logging records, appropriately formatted,
- to a stream. Note that this class does not close the stream, as
- sys.stdout or sys.stderr may be used.
-
- Slightly modified version of the StreamHandler class that ships with
- logging module.
-
- """
- def __init__(self, strm=None):
- """
- Initialize the handler.
-
- If strm is not specified, sys.stderr is used.
- """
- logging.Handler.__init__(self)
- if strm is None:
- strm = sys.stderr
- self.stream = strm
- self.formatter = None
-
- def flush(self):
- """
- Flush the stream.
- """
- self.stream.flush()
-
- def emit(self, record):
- """
- Emit a record.
-
- If a formatter is specified, it is used to format the record. The
- record is then written to the stream. If exception information is
- present, it is formatted using traceback.print_exception and
- appended to the stream.
- """
- try:
- msg = self.format(record)
- fs = "%s"
- if isinstance(msg, str):
- self.stream.write(fs % msg)
- else:
- try:
- self.stream.write(fs % msg.encode(config.console_encoding,
- "xmlcharrefreplace"))
- except UnicodeError:
- self.stream.write(fs % msg.encode("ascii",
- "xmlcharrefreplace"))
- self.flush()
- except (KeyboardInterrupt, SystemExit):
- raise
- except:
- self.handleError(record)
-
-
-
# User interface initialization
# search for user interface module in the 'userinterfaces' subdirectory
exec ("import pywikibot.userinterfaces.%s_interface as uiModule"
% config.userinterface)
ui = uiModule.UI()
+TerminalHandler = uiModule.TerminalHandler
+
+class RotatingFileHandler(logging.handlers.RotatingFileHandler):
+ """Strip trailing newlines before outputting text to file"""
+ def emit(self, record):
+ record.msg = record.msg.rstrip("\r\n")
+ logging.handlers.RotatingFileHandler.emit(self, record)
+
+
def output(text, decoder=None, newline=True, toStdout=False, level=INFO):
"""Output a message to the user via the userinterface.
@@ -263,7 +215,7 @@
logfile = config.datafilepath(config.logfilename)
else:
logfile = config.datafilepath("%s-bot.log" % moduleName)
- file_handler = logging.handlers.RotatingFileHandler(
+ file_handler = RotatingFileHandler(
filename=logfile, maxBytes=2 << 20, backupCount=5)
file_handler.setLevel(DEBUG)
Modified: branches/rewrite/pywikibot/userinterfaces/terminal_interface.py
===================================================================
--- branches/rewrite/pywikibot/userinterfaces/terminal_interface.py 2009-02-23 15:14:27 UTC (rev 6430)
+++ branches/rewrite/pywikibot/userinterfaces/terminal_interface.py 2009-02-23 19:19:09 UTC (rev 6431)
@@ -119,68 +119,6 @@
self.writelock = threading.RLock()
pass
- def printColorizedInUnix(self, text, level):
- lastColor = None
- for key, value in unixColors.iteritems():
- text = text.replace('\03{%s}' % key, value)
- # just to be sure, reset the color
- text += unixColors['default']
- logging.log(level, text)
-
- def printColorizedInWindows(self, text, level):
- """
- This only works in Python 2.5 or higher.
- """
- if ctypes_found:
- std_out_handle = ctypes.windll.kernel32.GetStdHandle(-11)
- # Color tags might be cascaded, e.g. because of transliteration.
- # Therefore we need this stack.
- colorStack = []
- tagM = True
- while tagM:
- tagM = colorTagR.search(text)
- if tagM:
- # print the text up to the tag.
- logging.log(level, text[:tagM.start()])
- newColor = tagM.group('name')
- if newColor == 'default':
- if len(colorStack) > 0:
- colorStack.pop()
- if len(colorStack) > 0:
- lastColor = colorStack[-1]
- else:
- lastColor = 'default'
- ctypes.windll.kernel32.SetConsoleTextAttribute(std_out_handle, windowsColors[lastColor])
- else:
- colorStack.append(newColor)
- # set the new color
- ctypes.windll.kernel32.SetConsoleTextAttribute(std_out_handle, windowsColors[newColor])
- text = text[tagM.end():]
- # print the rest of the text
- logging.log(level, text)
- # just to be sure, reset the color
- ctypes.windll.kernel32.SetConsoleTextAttribute(std_out_handle, windowsColors['default'])
- else:
- # ctypes is only available since Python 2.5, and we won't
- # try to colorize without it. Instead we add *** after the text as a whole
- # if anything needed to be colorized.
- lines = text.split('\n')
- for line in lines:
- line, count = colorTagR.subn('', line)
- if count > 0:
- line += '***'
- line += '\n'
- logging.log(level, line)
-
- def printColorized(self, text, level):
- if config.colorized_output:
- if sys.platform == 'win32':
- self.printColorizedInWindows(text, level)
- else:
- self.printColorizedInUnix(text, level)
- else:
- logging.log(level, text)
-
def output(self, text, level=logging.INFO):
"""
If a character can't be displayed in the encoding used by the user's
@@ -229,10 +167,9 @@
prev = transliterated[-1:]
prevchar = char
text = u"".join(transliteratedText)
-
self.writelock.acquire()
try:
- self.printColorized(text, level)
+ logging.log(level, text)
finally:
self.writelock.release()
@@ -302,8 +239,6 @@
finally:
self.writelock.release()
return answer
-
-
def editText(self, text, jumpIndex = None, highlight = None):
"""
@@ -327,7 +262,126 @@
import webbrowser
pywikibot.output(u'Opening CAPTCHA in your web browser...')
webbrowser.open(url)
- return pywikibot.input(u'What is the solution of the CAPTCHA that is shown in your web browser?')
+ return pywikibot.input(
+ u'What is the solution of the CAPTCHA that is shown in your web browser?')
except:
- pywikibot.output(u'Error in opening web browser: %s' % sys.exc_info()[0])
- return pywikibot.input(u'What is the solution of the CAPTCHA at %s ?' % url)
+ pywikibot.output(u'Error in opening web browser: %s'
+ % sys.exc_info()[0])
+ return pywikibot.input(
+ u'What is the solution of the CAPTCHA at %s ?' % url)
+
+
+class TerminalHandler(logging.Handler):
+ """A handler class that writes logging records, appropriately formatted, to
+ a stream connected to a terminal. This class does not close the stream,
+ as sys.stdout or sys.stderr may be (and usually will be) used.
+
+ Slightly modified version of the StreamHandler class that ships with
+ logging module, plus code for colorization of output.
+
+ """
+
+ def __init__(self, strm=None):
+ """Initialize the handler.
+
+ If strm is not specified, sys.stderr is used.
+
+ """
+ logging.Handler.__init__(self)
+ if strm is None:
+ strm = sys.stderr
+ self.stream = strm
+ self.formatter = None
+
+ def flush(self):
+ """Flush the stream. """
+ self.stream.flush()
+
+ def emit_raw(self, record, msg):
+ """Emit a formatted message.
+
+ The message is written to the stream. If exception information is
+ present, it is formatted using traceback.print_exception and
+ appended to the stream.
+
+ """
+ try:
+ fs = "%s"
+ if isinstance(msg, str):
+ self.stream.write(fs % msg)
+ else:
+ try:
+ self.stream.write(fs % msg.encode(config.console_encoding,
+ "xmlcharrefreplace"))
+ except UnicodeError:
+ self.stream.write(fs % msg.encode("ascii",
+ "xmlcharrefreplace"))
+ self.flush()
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except:
+ self.handleError(record)
+
+ def emitColorizedInUnix(self, record, msg):
+ lastColor = None
+ for key, value in unixColors.iteritems():
+ msg = msg.replace('\03{%s}' % key, value)
+ # just to be sure, reset the color
+ msg += unixColors['default']
+ self.emit_raw(record, msg)
+
+ def emitColorizedInWindows(self, record, msg):
+ """This only works in Python 2.5 or higher."""
+ if ctypes_found:
+ std_out_handle = ctypes.windll.kernel32.GetStdHandle(-11)
+ # Color tags might be cascaded, e.g. because of transliteration.
+ # Therefore we need this stack.
+ colorStack = []
+ tagM = True
+ while tagM:
+ tagM = colorTagR.search(msg)
+ if tagM:
+ # print the text up to the tag.
+ self.emit_raw(record, msg[:tagM.start()])
+ newColor = tagM.group('name')
+ if newColor == 'default':
+ if len(colorStack) > 0:
+ colorStack.pop()
+ if len(colorStack) > 0:
+ lastColor = colorStack[-1]
+ else:
+ lastColor = 'default'
+ ctypes.windll.kernel32.SetConsoleTextAttribute(
+ std_out_handle, windowsColors[lastColor])
+ else:
+ colorStack.append(newColor)
+ # set the new color
+ ctypes.windll.kernel32.SetConsoleTextAttribute(
+ std_out_handle, windowsColors[newColor])
+ msg = msg[tagM.end():]
+ # print the rest of the text
+ self.emit_raw(record, msg)
+ # just to be sure, reset the color
+ ctypes.windll.kernel32.SetConsoleTextAttribute(
+ std_out_handle, windowsColors['default'])
+ else:
+ # ctypes is only available since Python 2.5, and we won't
+ # try to colorize without it. Instead we add *** after the text
+ # as a whole if anything needed to be colorized.
+ lines = msg.split('\n')
+ for line in lines:
+ line, count = colorTagR.subn('', line)
+ if count > 0:
+ line += '***'
+ line += '\n'
+ self.emit_raw(record, line)
+
+ def emit(self, record):
+ msg = self.format(record)
+ if config.colorized_output:
+ if sys.platform == 'win32':
+ self.emitColorizedInWindows(record, msg)
+ else:
+ self.emitColorizedInUnix(record, msg)
+ else:
+ self.emit_raw(record, msg)