docker-offlineimap/offlineimap/ui/TTY.py
Sebastian Spaeth cbec8bb5b2 Rework UI system to make use of the logging module
Logging was flawed as the output was e.g. heavily buffered and people
complained about missing log entries. Fix this by making use of the
standard logging facilities that offlineimap offers.

This is one big ugly patch that does many things. It fixes the
Blinkenlights backend to work again with the logging facilities.

Resize windows and hotkeys are still not handled absolut correctly, this
is left for future fixing. THe rest of the backends should be working fine.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-10-27 16:23:55 +02:00

87 lines
3.3 KiB
Python

# TTY UI
# Copyright (C) 2002-2011 John Goerzen & contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import logging
import sys
from getpass import getpass
from offlineimap import banner
from offlineimap.ui.UIBase import UIBase
class TTYFormatter(logging.Formatter):
"""Specific Formatter that adds thread information to the log output"""
def __init__(self, *args, **kwargs):
super(TTYFormatter, self).__init__(*args, **kwargs)
self._last_log_thread = None
def format(self, record):
"""Override format to add thread information"""
log_str = super(TTYFormatter, self).format(record)
# If msg comes from a different thread than our last, prepend
# thread info. Most look like 'Account sync foo' or 'Folder
# sync foo'.
t_name = record.threadName
if t_name == 'MainThread':
return log_str # main thread doesn't get things prepended
if t_name != self._last_log_thread:
self._last_log_thread = t_name
log_str = "%s:\n %s" % (t_name, log_str)
else:
log_str = " %s" % log_str
return log_str
class TTYUI(UIBase):
def setup_consolehandler(self):
"""Backend specific console handler
Sets up things and adds them to self.logger.
:returns: The logging.Handler() for console output"""
# create console handler with a higher log level
ch = logging.StreamHandler()
#ch.setLevel(logging.DEBUG)
# create formatter and add it to the handlers
self.formatter = TTYFormatter("%(message)s")
ch.setFormatter(self.formatter)
# add the handlers to the logger
self.logger.addHandler(ch)
self.logger.info(banner)
# init lock for console output
ch.createLock()
return ch
def isusable(self):
"""TTYUI is reported as usable when invoked on a terminal"""
return sys.stdout.isatty() and sys.stdin.isatty()
def getpass(self, accountname, config, errmsg = None):
"""TTYUI backend is capable of querying the password"""
if errmsg:
self.warn("%s: %s" % (accountname, errmsg))
self._log_con_handler.acquire() # lock the console output
try:
return getpass("Enter password for account '%s': " % accountname)
finally:
self._log_con_handler.release()
def mainException(self):
if isinstance(sys.exc_info()[1], KeyboardInterrupt):
self.logger.warn("Timer interrupted at user request; program "
"terminating.\n")
self.terminate()
else:
UIBase.mainException(self)