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)