docker-offlineimap/offlineimap/ui/TTY.py

114 lines
4.1 KiB
Python
Raw Normal View History

# TTY UI
# Copyright (C) 2002-2018 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
2006-08-12 06:15:55 +02:00
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import logging
import sys
import time
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() doesn't work in py2.6 as 'logging' uses old-style class
logging.Formatter.__init__(self, *args, **kwargs)
self._last_log_thread = None
def format(self, record):
"""Override format to add thread information."""
# super() doesn't work in py2.6 as 'logging' uses old-style class
log_str = logging.Formatter.format(self, 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
2002-06-21 07:29:12 +02:00
2002-06-21 07:42:39 +02:00
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()
2002-06-21 07:29:12 +02:00
def getpass(self, username, config, errmsg=None):
"""TTYUI backend is capable of querying the password."""
if errmsg:
self.warn("%s: %s" % (username, errmsg))
self._log_con_handler.acquire() # lock the console output
try:
return getpass("Enter password for user '%s': " % username)
finally:
self._log_con_handler.release()
2002-06-21 07:42:39 +02:00
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)
def sleeping(self, sleepsecs, remainingsecs):
"""Sleep for sleepsecs, display remainingsecs to go.
Does nothing if sleepsecs <= 0.
Display a message on the screen if we pass a full minute.
This implementation in UIBase does not support this, but some
implementations return 0 for successful sleep and 1 for an
'abort', ie a request to sync immediately."""
if sleepsecs > 0:
if remainingsecs // 60 != (remainingsecs - sleepsecs) // 60:
self.logger.info("Next refresh in %.1f minutes" % (
remainingsecs / 60.0))
time.sleep(sleepsecs)
return 0