primitivus: use of new logging system:
- default output is \\memory
- logs can be seen with :messages command
- now useless writeLog method has been removed
This commit is contained in:
parent
468206e529
commit
39989cc985
7 changed files with 80 additions and 43 deletions
|
|
@ -79,4 +79,6 @@ class Const(constants.Const):
|
|||
"dnd": (u'✖', "show_dnd"),
|
||||
"xa": (u'☄', "show_xa")
|
||||
}
|
||||
LOG_OPT_SECTION = APP_NAME.lower()
|
||||
LOG_OPT_OUTPUT = ('output', constants.Const.LOG_OPT_OUTPUT_SEP + constants.Const.LOG_OPT_OUTPUT_MEMORY)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
|
||||
|
||||
from sat.core.i18n import _
|
||||
from sat_frontends.primitivus.constants import Const as C
|
||||
from sat.core import log as logging
|
||||
logging.satConfigure(C.LOG_BACKEND_STANDARD, C)
|
||||
log = logging.getLogger(__name__)
|
||||
import urwid
|
||||
from urwid_satext import sat_widgets
|
||||
from urwid_satext.files_management import FileDialog
|
||||
|
|
@ -32,19 +36,11 @@ from sat_frontends.primitivus.xmlui import XMLUI
|
|||
from sat_frontends.primitivus.progress import Progress
|
||||
from sat_frontends.primitivus.notify import Notify
|
||||
from sat_frontends.tools.misc import InputHistory
|
||||
from sat_frontends.primitivus.constants import Const
|
||||
from sat_frontends.constants import Const as commonConst
|
||||
import logging
|
||||
from logging import debug, info, error
|
||||
from sat_frontends.constants import Const as commonConst # FIXME
|
||||
from sat.tools.jid import JID
|
||||
from os.path import join
|
||||
|
||||
|
||||
### logging configuration FIXME: put this elsewhere ###
|
||||
logging.basicConfig(level=logging.CRITICAL, #TODO: configure it to put messages in a log file
|
||||
format='%(message)s')
|
||||
###
|
||||
|
||||
class ChatList(QuickChatList):
|
||||
"""This class manage the list of chat windows"""
|
||||
|
||||
|
|
@ -119,6 +115,9 @@ class EditBar(sat_widgets.ModalEdit):
|
|||
if command == 'quit':
|
||||
self.app.onExit()
|
||||
raise urwid.ExitMainLoop()
|
||||
elif command == 'messages':
|
||||
wid = sat_widgets.GenericList(logging.memoryGet())
|
||||
self.app.addWindow(wid)
|
||||
elif command == 'presence':
|
||||
self.app.status_bar.onPresenceClick()
|
||||
elif command in ['presence %s' % show for show in commonConst.PRESENCE.keys()]:
|
||||
|
|
@ -166,7 +165,7 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
|
||||
## main loop setup ##
|
||||
self.main_widget = ProfileManager(self)
|
||||
self.loop = urwid.MainLoop(self.main_widget, Const.PALETTE, event_loop=urwid.GLibEventLoop(), input_filter=self.inputFilter, unhandled_input=self.keyHandler)
|
||||
self.loop = urwid.MainLoop(self.main_widget, C.PALETTE, event_loop=urwid.GLibEventLoop(), input_filter=self.inputFilter, unhandled_input=self.keyHandler)
|
||||
|
||||
##misc setup##
|
||||
self.chat_wins = ChatList(self)
|
||||
|
|
@ -187,25 +186,25 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
self.editBar.mode = value
|
||||
|
||||
def modeHint(self, value):
|
||||
"""Change mode if make sens (i.e.: if there is nothing in the editBar"""
|
||||
"""Change mode if make sens (i.e.: if there is nothing in the editBar)"""
|
||||
if not self.editBar.get_edit_text():
|
||||
self.mode = value
|
||||
|
||||
def debug(self):
|
||||
"""convenient method to reset screen and launch p(u)db"""
|
||||
"""convenient method to reset screen and launch (i)p(u)db"""
|
||||
log.info('Entered debug mode')
|
||||
try:
|
||||
import pudb
|
||||
pudb.set_trace()
|
||||
except:
|
||||
import os,pdb
|
||||
except ImportError:
|
||||
import os
|
||||
os.system('reset')
|
||||
print 'Entered debug mode'
|
||||
pdb.set_trace()
|
||||
|
||||
def writeLog(self, log, file_name='/tmp/primitivus_log'):
|
||||
"""method to write log in a temporary file, useful for debugging"""
|
||||
with open(file_name, 'a') as f:
|
||||
f.write(log+"\n")
|
||||
try:
|
||||
import ipdb
|
||||
ipdb.set_trace()
|
||||
except ImportError:
|
||||
import pdb
|
||||
pdb.set_trace()
|
||||
|
||||
def redraw(self):
|
||||
"""redraw the screen"""
|
||||
|
|
@ -296,7 +295,7 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
menu.addMenu(communication, _("Join room"), self.onJoinRoomRequest, 'meta j')
|
||||
#additionals menus
|
||||
#FIXME: do this in a more generic way (in quickapp)
|
||||
add_menus = self.bridge.getMenus('', Const.NO_SECURITY_LIMIT)
|
||||
add_menus = self.bridge.getMenus('', C.NO_SECURITY_LIMIT)
|
||||
def add_menu_cb(callback_id):
|
||||
self.launchAction(callback_id, None, profile_key = self.profile)
|
||||
for id_, type_, path, path_i18n in add_menus:
|
||||
|
|
@ -417,7 +416,7 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
no_cb=self._dialogCancelCb, no_value = (answer_cb, answer_data))
|
||||
else:
|
||||
popup = sat_widgets.Alert(unicode(title), unicode(message), ok_cb=answer_cb or self.removePopUp) #FIXME: remove unicode here when DBus Bridge will no return dbus.String anymore
|
||||
error(_('unmanaged dialog type: %s'), type_)
|
||||
log.error(_('unmanaged dialog type: %s'), type_)
|
||||
self.showPopUp(popup)
|
||||
|
||||
def onNotification(self, notBar):
|
||||
|
|
@ -432,7 +431,7 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
self.main_widget.footer = pile
|
||||
else:
|
||||
if not isinstance(self.main_widget.footer, urwid.Pile):
|
||||
error(_("INTERNAL ERROR: Unexpected class for main widget's footer"))
|
||||
log.error(_("INTERNAL ERROR: Unexpected class for main widget's footer"))
|
||||
assert(False)
|
||||
if self.notBar.canHide():
|
||||
#No notification left, we can hide the bar
|
||||
|
|
@ -499,13 +498,13 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
return
|
||||
|
||||
if not id in self.current_action_ids:
|
||||
debug (_('unknown id, ignoring'))
|
||||
log.debug (_('unknown id, ignoring'))
|
||||
return
|
||||
if type_ == "SUPPRESS":
|
||||
self.current_action_ids.remove(id)
|
||||
elif type_ == "XMLUI":
|
||||
self.current_action_ids.remove(id)
|
||||
debug (_("XML user interface received"))
|
||||
log.debug (_("XML user interface received"))
|
||||
misc = {}
|
||||
#FIXME FIXME FIXME: must clean all this crap !
|
||||
title = _('Form')
|
||||
|
|
@ -534,7 +533,7 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
del self.current_action_ids_cb[id]
|
||||
callback(data)
|
||||
else:
|
||||
error (_("FIXME FIXME FIXME: type [%s] not implemented") % type_)
|
||||
log.error (_("FIXME FIXME FIXME: type [%s] not implemented") % type_)
|
||||
raise NotImplementedError
|
||||
|
||||
##DIALOGS CALLBACKS##
|
||||
|
|
@ -545,7 +544,7 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
self.bridge.joinMUC(room_jid, self.profiles[self.profile]['whoami'].node, {}, self.profile)
|
||||
else:
|
||||
message = _("'%s' is an invalid JID !") % room_jid
|
||||
error (message)
|
||||
log.error (message)
|
||||
self.showPopUp(sat_widgets.Alert(_("Error"), message, ok_cb=self.removePopUp))
|
||||
|
||||
#MENU EVENTS#
|
||||
|
|
@ -561,7 +560,7 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
|
||||
def failure(error):
|
||||
self.showPopUp(sat_widgets.Alert(_("Error"), _("Can't get parameters"), ok_cb=self.removePopUp))
|
||||
self.bridge.getParamsUI(app=Const.APP_NAME, profile_key=self.profile, callback=success, errback=failure)
|
||||
self.bridge.getParamsUI(app=C.APP_NAME, profile_key=self.profile, callback=success, errback=failure)
|
||||
|
||||
def onExitRequest(self, menu):
|
||||
QuickApp.onExit(self)
|
||||
|
|
@ -573,7 +572,7 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
self.showPopUp(pop_up_widget)
|
||||
|
||||
def onAboutRequest(self, menu):
|
||||
self.showPopUp(sat_widgets.Alert(_("About"), Const.APP_NAME + " v" + self.bridge.getVersion(), ok_cb=self.removePopUp))
|
||||
self.showPopUp(sat_widgets.Alert(_("About"), C.APP_NAME + " v" + self.bridge.getVersion(), ok_cb=self.removePopUp))
|
||||
|
||||
#MISC CALLBACKS#
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
from sat.core.i18n import _
|
||||
import urwid
|
||||
from urwid_satext.sat_widgets import AdvancedEdit,Password,List,InputDialog,ConfirmDialog,Alert,FocusFrame
|
||||
from urwid_satext.sat_widgets import AdvancedEdit,Password,List,InputDialog,ConfirmDialog,Alert
|
||||
from sat.tools.jid import JID
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ from sat.core.i18n import _
|
|||
import urwid
|
||||
import copy
|
||||
from urwid_satext import sat_widgets
|
||||
from logging import debug, info, warning, error
|
||||
from sat.core.log import getLogger
|
||||
log = getLogger(__name__)
|
||||
from xml.dom import minidom
|
||||
from sat_frontends.tools import xmlui
|
||||
|
||||
|
|
@ -74,7 +75,7 @@ class PrimitivusDividerWidget(xmlui.DividerWidget, urwid.Divider):
|
|||
elif style == 'blank':
|
||||
div_char = ' '
|
||||
else:
|
||||
warning(_("Unknown div_char"))
|
||||
log.warning(_("Unknown div_char"))
|
||||
div_char = u'─'
|
||||
|
||||
urwid.Divider.__init__(self, div_char)
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ class Const(object):
|
|||
LOG_BACKEND_BASIC = 'basic'
|
||||
LOG_BASE_LOGGER = 'root'
|
||||
LOG_TWISTED_LOGGER = 'twisted'
|
||||
LOG_OPT_SECTION = 'DEFAULT' # section of sat.conf where log options should be
|
||||
LOG_OPT_PREFIX = 'log_'
|
||||
# (option_name, default_value) tuples
|
||||
LOG_OPT_COLORS = ('colors', 'true') # true for auto colors, force to have colors even if stdout is not a tty, false for no color
|
||||
|
|
@ -91,7 +92,6 @@ class Const(object):
|
|||
LOG_OPT_OUTPUT_MEMORY_LIMIT = 50
|
||||
LOG_OPT_OUTPUT_FILE = 'file' # file is implicit if only output
|
||||
LOG_OPT_OUTPUT = ('output', LOG_OPT_OUTPUT_SEP + LOG_OPT_OUTPUT_DEFAULT) # //default = normal output (stderr or a file with twistd), path/to/file for a file (must be the first if used), //memory for memory (options can be put in parenthesis, e.g.: //memory(500) for a 500 lines memory)
|
||||
LOG_OPTIONS = (LOG_OPT_COLORS, LOG_OPT_LEVEL, LOG_OPT_FORMAT, LOG_OPT_LOGGER, LOG_OPT_OUTPUT)
|
||||
LOG_LVL_DEBUG = 'DEBUG'
|
||||
LOG_LVL_INFO = 'INFO'
|
||||
LOG_LVL_WARNING = 'WARNING'
|
||||
|
|
@ -115,3 +115,10 @@ class Const(object):
|
|||
ANSI_BOLD = '\033[1m'
|
||||
ANSI_BLINK = '\033[5m'
|
||||
ANSI_BLINK_OFF = '\033[25m'
|
||||
|
||||
@classmethod
|
||||
def LOG_OPTIONS(cls):
|
||||
"""Return options checked for logs"""
|
||||
# XXX: we use a classmethod so we can use Const inheritance to change default options
|
||||
return(cls.LOG_OPT_COLORS, cls.LOG_OPT_LEVEL, cls.LOG_OPT_FORMAT, cls.LOG_OPT_LOGGER, cls.LOG_OPT_OUTPUT)
|
||||
|
||||
|
|
|
|||
|
|
@ -169,6 +169,18 @@ class FilterName(object):
|
|||
log_record.name = dict_record['name']
|
||||
return self.filter(log_record) == 1
|
||||
|
||||
def memoryGet(size=None):
|
||||
"""Return buffered logs
|
||||
|
||||
@param size: number of logs to return
|
||||
"""
|
||||
if not C.LOG_OPT_OUTPUT_MEMORY in _handlers:
|
||||
raise ValueError('memory output is not used')
|
||||
if _backend == C.LOG_BACKEND_STANDARD:
|
||||
mem_handler = _handlers[C.LOG_OPT_OUTPUT_MEMORY]
|
||||
return (log_msg for log_msg in mem_handler.buffer[size if size is None else -size:])
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
def _getProfile():
|
||||
"""Try to find profile value using introspection"""
|
||||
|
|
@ -509,7 +521,11 @@ class ConfigureTwisted(ConfigureBasic):
|
|||
|
||||
class ConfigureStandard(Configure):
|
||||
|
||||
def __init__(self, level=None, fmt=C.LOG_OPT_FORMAT[1], output=C.LOG_OPT_OUTPUT[1], logger=None, colors=False, force_colors=False):
|
||||
def __init__(self, level=None, fmt=None, output=None, logger=None, colors=False, force_colors=False):
|
||||
if fmt is None:
|
||||
fmt = C.LOG_OPT_FORMAT[1]
|
||||
if output is None:
|
||||
output = C.LOG_OPT_OUTPUT[1]
|
||||
super(ConfigureStandard, self).__init__(level, fmt, output, logger, colors, force_colors)
|
||||
|
||||
def preTreatment(self):
|
||||
|
|
@ -559,7 +575,7 @@ class ConfigureStandard(Configure):
|
|||
|
||||
def configureColors(self, colors, force_colors):
|
||||
import sys
|
||||
self.with_color = colors & (sys.stdout.isatty() or force_colors)
|
||||
self.formatter.with_color = colors & (sys.stdout.isatty() or force_colors)
|
||||
if not colors and force_colors:
|
||||
raise ValueError("force_colors can't be used if colors is False")
|
||||
|
||||
|
|
@ -579,8 +595,11 @@ class ConfigureStandard(Configure):
|
|||
hdlr = logging.StreamHandler()
|
||||
self._addHandler(root_logger, hdlr)
|
||||
elif handler == C.LOG_OPT_OUTPUT_MEMORY:
|
||||
import logging.handlers
|
||||
hdlr = logging.handlers.BufferingHandler(options)
|
||||
from logging.handlers import BufferingHandler
|
||||
class SatMemoryHandler(BufferingHandler):
|
||||
def emit(self, record):
|
||||
super(SatMemoryHandler, self).emit(self.format(record))
|
||||
hdlr = SatMemoryHandler(options)
|
||||
_handlers[handler] = hdlr # we keep a reference to the handler to read the buffer later
|
||||
self._addHandler(root_logger, hdlr)
|
||||
elif handler == C.LOG_OPT_OUTPUT_FILE:
|
||||
|
|
@ -640,23 +659,31 @@ def _parseOptions(options):
|
|||
level = C.LOG_LVL_INFO
|
||||
options[LEVEL] = level
|
||||
|
||||
def satConfigure(backend=C.LOG_BACKEND_TWISTED):
|
||||
def satConfigure(backend=C.LOG_BACKEND_STANDARD, const=None):
|
||||
"""Configure logging system for SàT, can be used by frontends
|
||||
|
||||
logs conf is read in SàT conf, then in environment variables. It must be done before Memory init
|
||||
@param backend: backend to use, it can be:
|
||||
- C.LOG_BACKEND_BASIC: print based backend
|
||||
- C.LOG_BACKEND_TWISTED: Twisted logging backend
|
||||
- C.LOG_BACKEND_STANDARD: standard logging backend
|
||||
@param const: Const class to use instead of sat.core.constants.Const (mainly used to change default values)
|
||||
"""
|
||||
if const is not None:
|
||||
global C
|
||||
C = const
|
||||
import ConfigParser
|
||||
import os
|
||||
log_conf = {}
|
||||
config = ConfigParser.SafeConfigParser()
|
||||
config.read(C.CONFIG_FILES)
|
||||
for opt_name, opt_default in C.LOG_OPTIONS:
|
||||
for opt_name, opt_default in C.LOG_OPTIONS():
|
||||
try:
|
||||
log_conf[opt_name] = os.environ[''.join((C.ENV_PREFIX, C.LOG_OPT_PREFIX.upper(), opt_name.upper()))]
|
||||
except KeyError:
|
||||
try:
|
||||
log_conf[opt_name] = config.get('DEFAULT', C.LOG_OPT_PREFIX + opt_name)
|
||||
except ConfigParser.NoOptionError:
|
||||
log_conf[opt_name] = config.get(C.LOG_OPT_SECTION, C.LOG_OPT_PREFIX + opt_name)
|
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
|
||||
log_conf[opt_name] = opt_default
|
||||
|
||||
_parseOptions(log_conf)
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@ from twisted.internet import glib2reactor
|
|||
glib2reactor.install()
|
||||
|
||||
# XXX: We need to configure logs before any log method is used, so here is the best place.
|
||||
from sat.core.constants import Const as C
|
||||
from sat.core import log
|
||||
log.satConfigure()
|
||||
log.satConfigure(C.LOG_BACKEND_TWISTED)
|
||||
|
||||
# XXX: SAT must be imported after log configuration, because it write stuff to logs
|
||||
from sat.core.sat_main import SAT
|
||||
|
|
|
|||
Loading…
Reference in a new issue