#!/usr/bin/env python
#
# Copyright 2001-2004 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the standalone Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A simple-minded GUI configurator for the logging module, using Tkinter.
Should work under Python versions >= 1.5.2.
Copyright (C) 2002-2004 Vinay Sajip. All Rights Reserved.
Configuration files are read/written using ConfigParser.
"""
"""
(C) 2002 Vinay Sajip. All rights reserved.
"""
from Tkinter import *
from tkFileDialog import *
from tkMessageBox import *
import os, sys, string, types
import ConfigParser
active = None
__version__ = "0.4.1"
DEFAULT_FILENAME = "logconf.ini"
LOGGING_LEVELS = (
("NOTSET", "NOTSET"),
("DEBUG", "DEBUG"),
("INFO", "INFO"),
("WARNING", "WARNING"),
("ERROR", "ERROR"),
("CRITICAL", "CRITICAL")
)
HANDLER_TYPES = (
("StreamHandlerProxy", "StreamHandler"),
("FileHandlerProxy", "FileHandler"),
("RotatingFileHandlerProxy", "RotatingFileHandler"),
("SocketHandlerProxy", "SocketHandler"),
("DatagramHandlerProxy", "DatagramHandler"),
("SysLogHandlerProxy", "SysLogHandler"),
("NTEventLogHandlerProxy", "NTEventLogHandler"),
("SMTPHandlerProxy", "SMTPHandler"),
("MemoryHandlerProxy", "MemoryHandler"),
("HTTPHandlerProxy", "HTTPHandler"),
# ("SOAPHandlerProxy", "SOAPHandler"),
)
OUTPUT_STREAMS = (
("sys.stdout", "sys.stdout"),
("sys.stderr", "sys.stderr")
)
FILE_MODES = (
("a", "a"),
("w", "w")
)
HTTP_METHODS = (
("GET", "GET"),
("POST", "POST")
)
SYSLOG_FACILITIES = (
("LOG_AUTH", "auth"),
("LOG_AUTHPRIV", "authpriv"),
("LOG_CRON", "cron"),
("LOG_DAEMON", "daemon"),
("LOG_KERN", "kern"),
("LOG_LPR", "lpr"),
("LOG_MAIL", "mail"),
("LOG_NEWS", "news"),
("LOG_AUTH", "security"),
("LOG_SYSLOG", "syslog"),
("LOG_USER", "user"),
("LOG_UUCP", "uucp"),
("LOG_LOCAL0", "local0"),
("LOG_LOCAL1", "local1"),
("LOG_LOCAL2", "local2"),
("LOG_LOCAL3", "local3"),
("LOG_LOCAL4", "local4"),
("LOG_LOCAL5", "local5"),
("LOG_LOCAL6", "local6"),
("LOG_LOCAL7", "local7"),
)
LOG_TYPES = (
("Application", "Application"),
("System", "System"),
("Security", "Security")
)
BOOLEAN_VALUES = (
("0", "False"),
("1", "True")
)
class Property:
def __init__(self, name, caption, value=None, choices=None):
self.name = name
self.caption = caption
self.value = value
self.choices = choices
def getChoices(self):
return self.choices
def isvalid(self, s):
return 0
def getCaption(self):
return self.caption
def getValue(self):
return self.value
def getChoiceText(self, val):
rv = ""
choices = self.getChoices()
if choices:
for choice in choices:
if choice[0] == val:
rv = choice[1]
break
return rv
def setValue(self, val):
self.value = val
def getValueText(self):
if type(self.value) in [types.ListType, types.TupleType]:
v = list(self.value)
else:
v = [self.value]
choices = self.getChoices()
if choices:
v = map(self.getChoiceText, v)
return string.join(v, ',')
class PropertyHolder:
def __init__(self, dict):
self.dict = dict
self.propnames = []
self.onPropListChanged = None
def getPropNames(self):
"""
Return the property names in the order in which they are to
be listed.
"""
return self.propnames
def getProp(self, name):
return self.dict[name]
def isReadonly(self, name):
return 0
#convenience methods
def getPropValue(self, name):
return self.dict[name].value
def setPropValue(self, name, value):
self.dict[name].setValue(value)
LINE_COLOUR = '#999999'
class ScrollingList(Frame):
def __init__(self, parent, *args, **kwargs):
Frame.__init__(self, parent)
self.parent = parent
self.listener = self.parent
self.sb = Scrollbar(self, orient=VERTICAL)
kwargs["yscrollcommand"] = self.sb.set
self.list = apply(Listbox, (self,) + args, kwargs)
self.sb.config(command=self.list.yview)
self.sb.pack(side=RIGHT, fill=Y)
self.list.pack(side=LEFT, fill=BOTH,expand=1)
self.list.bind('<ButtonRelease-1>', self.onListChange)
self.choices = None
def setContents(self, choices, value):
self.choices = choices
self.value = value
self.list.delete(0, END)
if type(value) == types.ListType:
sm = EXTENDED
else:
sm = BROWSE
self.list.configure(selectmode=sm)
i = 0
for choice in choices:
self.list.insert(END, choice[1])
if sm == EXTENDED:
if choice[0] in value:
self.list.select_set(i)
else:
if choice[0] == value:
self.list.select_set(i)
i = i + 1
def getValue(self):
if type(self.value) == types.ListType:
multi = 1
rv = []
else:
multi = 0
for i in xrange(len(self.choices)):
if self.list.select_includes(i):
if not multi:
rv = self.choices[i][0]
break
else:
rv.append(self.choices[i][0])
return rv
def onListChange(self, event):
self.value = self.getValue()
self.listener.onListChange(self.value)
class PropertyHeader(Canvas):
def __init__(self, parent, *args, **kwargs):
self.namewidth = 120
if kwargs.has_key("namewidth"):
self.namewidth = kwargs["namewidth"]
del kwargs["namewidth"]
self.rowheight = 16
if kwargs.has_key("rowheight"):
self.rowheight = kwargs["rowheight"]
del kwargs["rowheight"]
apply(Canvas.__init__, (self, parent)+args, kwargs)
self.bind('<Configure>', self.onConfigure)
x = 5
y = 0
wid = int(self.cget('width'))
self.create_text(x, y, text='Property', anchor='nw')
self.create_text(x + self.namewidth, y, text='Value', anchor='nw')
self.create_line(self.namewidth, 0, self.namewidth, self.rowheight, fill=LINE_COLOUR)
self.tline = self.create_line(0, 0, wid, 0, fill=LINE_COLOUR)
#self.create_line(0, 0, 0, self.rowheight, fill=LINE_COLOUR)
#self.create_line(wid - 1, 0, wid - 1, self.rowheight, fill=LINE_COLOUR)
def onConfigure(self, event):
self.delete(self.tline)
self.tline = self.create_line(0, 0, event.width, 0, fill=LINE_COLOUR)
_popup = None
class PropertyCanvas(Canvas):
def __init__(self, parent, *args, **kwargs):
self.namewidth = 120
if kwargs.has_key("namewidth"):
self.namewidth = kwargs["namewidth"]
del kwargs["namewidth"]
self.rowheight = 16
if kwargs.has_key("rowheight"):
self.rowheight = kwargs["rowheight"]
del kwargs["rowheight"]
apply(Canvas.__init__, (self, parent)+args, kwargs)
self.namitems = []
self.valitems = []
self.lines = []
self.pnames = []
#Event bindings...
self.bind('<Enter>', self.onEnter)
self.bind('<Button-1>', self.onClick)
self.bind('<Configure>', self.onConfigure)
self.button = Button(height=self.rowheight, width=self.rowheight, text='...', command=self.onEdit)
self.btnitem = None
self.editor = Entry()
self.edititem = None
self.popup = Toplevel()
self.popup.withdraw()
self.popup.overrideredirect(1)
self.list = ScrollingList(self.popup, background='white', relief=FLAT, borderwidth=0)
self.list.pack(fill=BOTH, expand=1)
self.list.listener = self
self.listvisible = 0
def clear(self):
for itm in self.namitems:
self.delete(itm)
self.namitems = []
for itm in self.valitems:
self.delete(itm)
self.valitems = []
for lin in self.lines:
self.delete(lin)
self.lines = []
def setPropertyHolder(self, ph):
self.ph = ph
self.pnames = ph.getPropNames()
wid = int(self.cget('width'))
hei = int(self.cget('height'))
self.clear()
x = 5
y = 0
i = 0
self.props = []
for n in self.pnames:
prop = self.ph.getProp(n)
self.props.append(prop)
tn = "n%d" % i
tv = "v%d" % i
self.namitems.append(self.create_text(x, y + 2, text=prop.getCaption(), anchor='nw', tags=tn))
self.valitems.append(self.create_text(x + self.namewidth, y + 2, text=prop.getValueText(), anchor='nw', tags=tv))
y = y + self.rowheight
i = i + 1
self.drawLines(wid, hei)
#self.config(height=y)
def drawLines(self, wid, hei):
for lin in self.lines:
self.delete(lin)
self.lines = []
y = 0
for i in xrange(len(self.pnames)):
self.lines.append(self.create_line(0, y, wid, y, fill=LINE_COLOUR))
y = y + self.rowheight
self.lines.append(self.create_line(0, y, wid, y, fill=LINE_COLOUR))
self.create_line(self.namewidth, 0, self.namewidth, hei, fill=LINE_COLOUR)
def onEnter(self, event):
if not self.edititem and not self.listvisible:
self.focus_set()
def hideControls(self):
if self.listvisible:
self.popup.withdraw()
global _popup
_popup = None
self.listvisible = 0
if self.edititem:
self.ph.setPropValue(self.editprop.name, self.editor.get())
self.itemconfig(self.valitems[self.editrow], text=self.editprop.getValueText())
self.delete(self.edititem)
self.edititem = None
if self.btnitem:
self.delete(self.btnitem)
self.btnitem = None
def onClick(self, event):
row = event.y / self.rowheight
self.hideControls()
if row < len(self.pnames):
wid = int(self.cget('width'))
hei = self.rowheight
prop = self.props[row]
if not self.ph.isReadonly(self.pnames[row]):
self.editrow = row
self.editprop = prop
choices = prop.getChoices()
if choices != None:
val = prop.getValue()
self.list.setContents(choices, val)
self.listy = row * hei + self.rowheight
self.btnitem = self.create_window(wid - hei, row * hei, width=hei, height=hei, window=self.button, anchor='nw', tags='button')
else:
self.editor.delete(0, END)
self.editor.insert(0, prop.getValueText())
self.editor.select_range(0, END)
self.edititem = self.create_window(self.namewidth + 1, row * hei, width=wid - self.namewidth, height = hei + 1, window=self.editor, anchor='nw', tags='editor')
self.editor.focus_set()
def onConfigure(self, event):
self.hideControls()
self.drawLines(event.width, event.height)
self.configure(width=event.width, height=event.height)
def onEdit(self):
wid = int(self.cget('width'))
#self.listitem = self.create_window(self.namewidth + 1, self.listy, width=wid - self.namewidth - 1, height = self.rowheight * 3, window=self.list, anchor='nw', tags='list')
w = wid - self.namewidth - 1
h = self.rowheight * 5
x = self.winfo_rootx() + self.namewidth + 1
y = self.winfo_rooty() + self.listy
s = "%dx%d+%d+%d" % (w, h, x, y)
self.popup.deiconify()
self.popup.lift()
self.popup.focus_set()
self.listvisible = 1
self.list.focus_set()
#For some reason with 1.5.2 (Windows), making the geometry call
#immediately following the assignment to s doesn't work. So we
#do it here
self.popup.geometry(s)
global _popup
_popup = self.popup
def onListChange(self, val):
self.ph.setPropValue(self.editprop.name, val)
self.itemconfig(self.valitems[self.editrow], text=self.editprop.getValueText())
if type(val) != types.ListType:
self.hideControls()
class PropertyEditor(Frame):
def __init__(self, parent, *args, **kwargs):
Frame.__init__(self, parent)
self.parent = parent
nw = kwargs.get("namewidth", 120)
rh = kwargs.get("rowheight", 16)
wid = kwargs.get("width", 300)
hei = kwargs.get("height", 60)
self.header = PropertyHeader(self, namewidth=nw, rowheight=rh, height=14, highlightthickness=0)
self.body = PropertyCanvas(self, namewidth=nw, rowheight=rh, width=wid, height=hei, background='white', highlightthickness=0)
self.header.pack(side=TOP, fill=X)
self.body.pack(side=BOTTOM, fill=BOTH, expand=1)
def setPropertyHolder(self, ph):
self.body.setPropertyHolder(ph)
class ADUPanel(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.add = Button(self, text="New", command=parent.onAdd)
self.add.pack(side=LEFT) #, fill=X, expand=1)
self.rmv = Button(self, text="Delete", command=parent.onDelete)
self.rmv.pack(side=LEFT) #, fill=X, expand=1)
#self.upd = Button(self, text="Update", command=parent.onUpdate)
#self.upd.pack(side=RIGHT, fill=X, expand=1)
class ScrollList(Frame):
def __init__(self, parent, *args, **kwargs):
Frame.__init__(self, parent)
self.parent = parent
self.sb = Scrollbar(self, orient=VERTICAL)
kwargs["yscrollcommand"] = self.sb.set
self.list = apply(Listbox, (self,) + args, kwargs)
self.sb.config(command=self.list.yview)
self.sb.pack(side=RIGHT, fill=Y)
self.list.pack(side=LEFT, fill=BOTH,expand=1)
def sortqn(log1, log2):
qn1 = log1.getQualifiedName()
qn2 = log2.getQualifiedName()
if qn1 == "(root)":
rv = -1
elif qn2 == "(root)":
rv = 1
else:
rv = cmp(qn1, qn2)
return rv
def sortn(obj1, obj2):
return cmp(obj1.getPropValue("name"), obj2.getPropValue("name"))
class LoggerPanel(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
label = Label(self, text="Loggers:")
label.grid(row=0, column=0, sticky='w')
self.slist = ScrollList(self, height=15, background='white')
self.slist.list.bind('<ButtonRelease-1>', self.onListChange)
self.slist.grid(row=1, column=0, sticky="nsew")
self.adu = ADUPanel(self)
self.adu.grid(row=2, column=0, sticky="we")
label = Label(self, text="Properties of selected logger:")
label.grid(row=3, column=0, sticky='w')
self.pe = PropertyEditor(self, height=120, borderwidth=1)
self.pe.grid(row=4, column=0, sticky='nsew')
self.columnconfigure(0, weight=1)
self.rowconfigure(1, weight=3)
self.rowconfigure(4, weight=1)
def setConfig(self, config):
self.config = config
#populate list of loggers
llist = config.getLoggers()
llist.sort(sortqn)
self.slist.list.delete(0, END)
self.pe.body.clear()
self.names = []
for logger in llist:
self.names.append(logger.getPropValue("name"))
self.slist.list.insert(END, logger.getQualifiedName())
def onAdd(self):
items = self.slist.list.curselection()
if not len(items):
showerror("No Parent Selected", "You haven't selected a parent logger.")
else:
idx = int(items[0])
parent = self.config.getLogger(self.names[idx])
log = self.config.getLogger(None)
log.onChannelChanged = self.onChannelChanged
log.setPropValue("parent", parent.getPropValue("name"))
self.names.insert(1 + idx, log.getPropValue("name"))
self.slist.list.insert(1 + idx, log.getQualifiedName())
self.slist.list.select_clear(0, END)
self.slist.list.select_set(1 + idx)
self.pe.setPropertyHolder(log)
def onDelete(self):
items = self.slist.list.curselection()
if not len(items):
showerror("No Item Selected", "You haven't selected anything to delete.")
else:
idx = int(items[0])
name = self.slist.list.get(idx)
if name == "(root)":
showerror("Root Item Selected", "You cannot delete the root logger.")
else:
resp = askyesno("Logger Deletion", "Are you sure you want to delete logger '%s'?" % name)
if resp:
#self.config.removeLogger(self.names[idx])
log = self.config.getLogger(self.names[idx])
log.deleted = 1
self.slist.list.delete(idx)
del self.names[idx]
self.pe.body.clear()
def onChannelChanged(self, nm, chname):
i = self.names.index(nm)
sel = i
while i < len(self.names):
log = self.config.getLogger(self.names[i])
self.slist.list.delete(i)
self.slist.list.insert(i, log.getQualifiedName())
i = i + 1
self.slist.list.select_clear(0, END)
self.slist.list.select_set(sel)
def onListChange(self, event):
self.pe.body.hideControls()
items = self.slist.list.curselection()
idx = int(items[0])
name = self.names[idx]
log = self.config.getLogger(name)
self.pe.setPropertyHolder(log)
class HandlerPanel(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
label = Label(self, text="Handlers:")
label.grid(row=0, column=0, sticky='w')
self.slist = ScrollList(self, height=6, background='white')
self.slist.list.bind('<ButtonRelease-1>', self.onListChange)
self.slist.grid(row=1, column=0, sticky="nsew")
self.adu = ADUPanel(self)
self.adu.grid(row=2, column=0, sticky="we")
label = Label(self, text="Properties of selected handler:")
label.grid(row=3, column=0, sticky='w')
self.pe = PropertyEditor(self, height=90, borderwidth=1)
self.pe.grid(row=4, column=0, sticky='nsew')
self.columnconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
self.rowconfigure(4, weight=1)
def setConfig(self, config):
self.config = config
#populate list of handlers
hlist = config.getHandlers()
hlist.sort(sortn)
self.slist.list.delete(0, END)
self.pe.body.clear()
for hand in hlist:
hand.onPropListChanged = self.onPropListChanged
self.slist.list.insert(END, hand.getPropValue("name"))
def onAdd(self):
self.pe.body.hideControls()
hand = self.config.getHandler(None)
self.slist.list.insert(END, hand.getProp("name").getValueText())
self.slist.list.select_clear(0, END)
self.slist.list.select_set(END)
hand.onPropListChanged = self.onPropListChanged
self.pe.setPropertyHolder(hand)
def onDelete(self):
items = self.slist.list.curselection()
if not len(items):
showerror("No Item Selected", "You haven't selected anything to delete")
else:
name = self.slist.list.get(int(items[0]))
log = self.config.handlerIsUsed(name)
if log:
showerror("Handler in use",
"The handler '%s' is being used by logger '%s'"\
", so it cannot be deleted." % (
name, log))
else:
self.config.removeHandler(name)
self.slist.list.delete(items)
self.pe.body.clear()
def onUpdate(self):
print "handler update"
def onListChange(self, event):
self.pe.body.hideControls()
items = self.slist.list.curselection()
name = self.slist.list.get(int(items[0]))
hand = self.config.getHandler(name)
self.pe.setPropertyHolder(hand)
def onPropListChanged(self, newhand):
newhand.onPropListChanged = self.onPropListChanged
self.pe.setPropertyHolder(newhand)
class FormatterPanel(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
label = Label(self, text="Formatters:")
label.grid(row=0, column=0, sticky='w')
self.slist = ScrollList(self, height=4, background='white')
self.slist.list.bind('<ButtonRelease-1>', self.onListChange)
self.slist.grid(row=1, column=0, sticky="nsew")
self.adu = ADUPanel(self)
self.adu.grid(row=2, column=0, sticky="ew")
label = Label(self, text="Properties of selected formatter:")
label.grid(row=3, column=0, sticky='w')
self.pe = PropertyEditor(self, height=60, borderwidth=1)
self.pe.grid(row=4, column=0, sticky='nsew')
self.columnconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
self.rowconfigure(4, weight=1)
def setConfig(self, config):
self.config = config
#populate list of formatters
flist = config.getFormatters()
flist.sort(sortn)
self.slist.list.delete(0, END)
self.pe.body.clear()
for form in flist:
self.slist.list.insert(END, form.getPropValue("name"))
def onAdd(self):
self.pe.body.hideControls()
fmt = self.config.getFormatter(None)
self.slist.list.insert(END, fmt.getProp("name").getValueText())
self.slist.list.select_clear(0, END)
i = self.slist.list.size()
self.slist.list.select_set(i - 1)
self.pe.setPropertyHolder(fmt)
def onDelete(self):
self.pe.body.hideControls()
items = self.slist.list.curselection()
if not len(items):
showerror("No Item Selected", "You haven't selected anything to delete")
else:
name = self.slist.list.get(int(items[0]))
h = self.config.formatterIsUsed(name)
if h:
showerror("Formatter in use",
"The formatter '%s' is being used by handler '%s'"\
", so it cannot be deleted." % (
name, h))
else:
self.config.removeFormatter(name)
self.slist.list.delete(items)
self.pe.body.clear()
def onUpdate(self):
self.pe.body.hideControls()
def onListChange(self, event):
self.pe.body.hideControls()
items = self.slist.list.curselection()
name = self.slist.list.get(int(items[0]))
fmt = self.config.getFormatter(name)
self.pe.setPropertyHolder(fmt)
class FilterPanel(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
label = Label(self, text="Filters:")
label.grid(row=0, column=0, sticky='w')
self.slist = ScrollList(self, height=4, background='white')
self.slist.list.bind('<ButtonRelease-1>', self.onListChange)
self.slist.grid(row=1, column=0, sticky="nsew")
self.adu = ADUPanel(self)
self.adu.grid(row=2, column=0, sticky="ew")
label = Label(self, text="Properties of selected filter:")
label.grid(row=3, column=0, sticky='w')
self.pe = PropertyEditor(self, height=60, borderwidth=1)
self.pe.grid(row=4, column=0, sticky='nsew')
self.columnconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
self.rowconfigure(4, weight=1)
def setConfig(self, config):
self.config = config
#populate list of filters
flist = config.getFilters()
flist.sort(sortn)
self.slist.list.delete(0, END)
self.pe.body.clear()
for filt in flist:
self.slist.list.insert(END, filt.getPropValue("name"))
def onAdd(self):
self.pe.body.hideControls()
filt = self.config.getFilter(None)
self.slist.list.insert(END, filt.getProp("name").getValueText())
self.slist.list.select_clear(0, END)
i = self.slist.list.size()
self.slist.list.select_set(i - 1)
self.pe.setPropertyHolder(filt)
def onDelete(self):
self.pe.body.hideControls()
items = self.slist.list.curselection()
if not len(items):
showerror("No Item Selected", "You haven't selected anything to delete")
else:
name = self.slist.list.get(int(items[0]))
h = self.config.filterIsUsed(name)
if h:
showerror("Filter in use",
"The filter '%s' is being used by '%s'"\
", so it cannot be deleted." % (
name, h))
else:
self.config.removeFilter(name)
self.slist.list.delete(items)
self.pe.body.clear()
def onUpdate(self):
self.pe.body.hideControls()
def onListChange(self, event):
self.pe.body.hideControls()
items = self.slist.list.curselection()
name = self.slist.list.get(int(items[0]))
filt = self.config.getFilter(name)
self.pe.setPropertyHolder(filt)
class ConfigPanel(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.load = Button(self, text="Load...", command=parent.onLoad)
self.load.pack(side=LEFT)
self.save = Button(self, text="Save", command=parent.onSave)
self.save.pack(side=LEFT)
self.save = Button(self, text="Save as...", command=parent.onSaveAs)
self.save.pack(side=LEFT)
self.reset = Button(self, text="Reset", command=parent.onReset)
self.reset.pack(side=RIGHT)
class Configurator(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.llist = LoggerPanel(self)
self.llist.grid(row=0, column=0, rowspan=2, sticky='nsew')
spacer = Canvas(self, width=2, highlightthickness=0)
spacer.grid(row=0, column=1, rowspan=2, sticky='ns')
self.hlist = HandlerPanel(self)
self.hlist.grid(row=0, column=2, sticky='nsew')
self.flist = FormatterPanel(self)
self.flist.grid(row=1, column=2, sticky='nsew')
self.cfg = ConfigPanel(self)
self.cfg.grid(row=2, column=0, columnspan=2, sticky='w')
self.filename = None
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
self.columnconfigure(2, weight=1)
label = Label(self, text="Copyright (C) 2002 Vinay Sajip. All rights reserved.", foreground='brown')
label.grid(row=3, column=0, columnspan=2, sticky='w')
if len(sys.argv) > 1:
fn = sys.argv[1]
try:
self.loadFile(fn)
except Exception, e:
print e
raise
else:
self.onReset(0)
self.setTitle()
self.focus_set()
def setTitle(self):
if self.filename:
s = os.path.split(self.filename)[1]
else:
s = "untitled"
self.winfo_toplevel().title("%s - Python Logging Configurator V%s" % (s, __version__))
def loadFile(self, fn):
self.config = LoggingConfig()
self.config.read(fn)
self.filename = fn
self.llist.setConfig(self.config)
self.hlist.setConfig(self.config)
self.flist.setConfig(self.config)
self.setTitle()
def onLoad(self):
fn = askopenfilename(title="Choose configuration file", filetypes=[("Logging configurations", "*.ini"), ("All files", "*.*")])
if fn:
self.loadFile(fn)
def onSaveAs(self):
if self.filename:
fn = os.path.split(self.filename)[1]
else:
fn = DEFAULT_FILENAME
fn = asksaveasfilename(title="Save configuration as", initialfile=fn, filetypes=[("Logging configurations", "*.ini"), ("All files", "*.*")])
if fn:
self.config.save(fn)
self.filename = fn
self.setTitle()
def onSave(self):
if not self.filename:
self.onSaveAs()
else:
self.config.save(self.filename)
def onReset(self, confirm=1):
if not confirm:
doit = 1
else:
doit = askyesno("Reset", "Are you sure you want to reset?")
if doit:
self.config = LoggingConfig()
self.llist.setConfig(self.config)
self.hlist.setConfig(self.config)
self.flist.setConfig(self.config)
self.setTitle()
# -- general properties
class NameProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "name", "Name", value)
class LevelProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "level", "Level", value)
def getChoices(self):
return LOGGING_LEVELS
# -- formatter properties
class FormatProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "format", "Format", value)
class DateFormatProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "datefmt", "Date Format", value)
class FormatterProxy(PropertyHolder):
def __init__(self, config, dict):
self.config = config
PropertyHolder.__init__(self, dict)
prop = NameProperty(dict.get("name", ""))
self.dict["name"] = prop
prop = FormatProperty(dict.get("format", "%(asctime)s %(levelname)s %(message)s"))
self.dict["format"] = prop
prop = DateFormatProperty(dict.get("datefmt", ""))
self.dict["datefmt"] = prop
self.propnames = ["name", "format", "datefmt"]
def isReadonly(self, name):
return name == "name"
def writeConfig(self, file):
file.write("[formatter_%s]\n" % self.getPropValue("name"))
file.write("format=%s\n" % self.getPropValue("format"))
file.write("datefmt=%s\n\n" % self.getPropValue("datefmt"))
# -- filter properties
class LoggerNameProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "lname", "Name", value)
class FilterProxy(PropertyHolder):
def __init__(self, config, dict):
self.config = config
PropertyHolder.__init__(self, dict)
prop = NameProperty(dict.get("name", ""))
self.dict["name"] = prop
prop = LoggerNameProperty(dict.get("lname", ""))
self.dict["lname"] = prop
self.propnames = ["name", "lname"]
def isReadonly(self, name):
return name == "name"
def writeConfig(self, file):
file.write("[filter_%s]\n" % self.getPropValue("name"))
file.write("lname=%s\n" % self.getPropValue("lname"))
# -- handler properties and proxies
class HandlerTypeProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "class", "Type", value)
def getChoices(self):
return HANDLER_TYPES
class FormatterProperty(Property):
def __init__(self, config, value=None):
self.config = config
Property.__init__(self, "formatter", "Formatter", value)
def getChoices(self):
return self.config.getFormatterChoice()
class HandlerProxy(PropertyHolder):
def __init__(self, config, dict):
self.config = config
PropertyHolder.__init__(self, dict)
prop = NameProperty(dict.get("name", ""))
self.dict["name"] = prop
prop = HandlerTypeProperty(dict.get("class", "StreamHandlerProxy"))
self.dict["class"] = prop
prop = FormatterProperty(self.config, dict.get("formatter", ""))
self.dict["formatter"] = prop
prop = LevelProperty(dict.get("level", "NOTSET"))
self.dict["level"] = prop
self.propnames = ["name", "class", "level", "formatter"]
def isReadonly(self, name):
return (name == "name")
def setPropValue(self, name, value):
PropertyHolder.setPropValue(self, name, value)
if (name == "class"): #morph type of handler
#print "try morph -> %s" % value
try:
klass = eval(value)
except Exception, e:
print e
klass = None
if klass:
n = self.getPropValue("name")
d = {
"name": n,
"class": value,
"formatter": self.getPropValue("formatter"),
"level": self.getPropValue("level"),
}
newhand = klass(self.config, d)
self.config.handlers[n] = newhand #FIXME encapsulation
if self.onPropListChanged:
self.onPropListChanged(newhand)
def writeConfig(self, file):
file.write("[handler_%s]\n" % self.getPropValue("name"))
s = self.getProp("class").getValueText()
if not s in ["StreamHandler", "FileHandler"]:
s = "handlers." + s
file.write("class=%s\n" % s)
file.write("level=%s\n" % self.getPropValue("level"))
file.write("formatter=%s\n" % self.getPropValue("formatter"))
class StreamProperty(Property):
def __init__(self, config, value=None):
self.config = config
Property.__init__(self, "stream", "Stream", value)
def getChoices(self):
return OUTPUT_STREAMS
class StreamHandlerProxy(HandlerProxy):
def __init__(self, config, dict):
HandlerProxy.__init__(self, config, dict)
prop = StreamProperty(self.config, dict.get("stream", "sys.stderr"))
self.dict["stream"] = prop
self.propnames.append("stream")
def writeConfig(self, file):
HandlerProxy.writeConfig(self, file)
file.write("stream=%s\n" % self.getPropValue("stream"))
file.write("args=(%s,)\n\n" % self.getPropValue("stream"))
def readConfig(self, sectname):
prop = StreamProperty(self.config, self.config.get(sectname, "stream"))
self.dict["stream"] = prop
self.propnames.append("stream")
class FilenameProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "filename", "File name", value)
class ModeProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "mode", "Mode", value)
def getChoices(self):
return FILE_MODES
class MaxSizeProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "maxsize", "Maximum Size (bytes)", value)
class BackupCountProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "backcount", "Backup Count", value)
class FileHandlerProxy(HandlerProxy):
def __init__(self, config, dict):
HandlerProxy.__init__(self, config, dict)
prop = FilenameProperty(dict.get("filename", "python.log"))
self.dict["filename"] = prop
prop = ModeProperty(dict.get("mode", "a"))
self.dict["mode"] = prop
self.propnames.extend(["filename", "mode"])
def writeConfig(self, file):
HandlerProxy.writeConfig(self, file)
fn = self.getPropValue("filename")
file.write("filename=%s\n" % fn)
mode = self.getPropValue("mode")
file.write("mode=%s\n" % mode)
file.write("args=('%s', '%s')\n\n" % (fn, mode))
def readConfig(self, sectname):
prop = FilenameProperty(self.config.get(sectname, "filename"))
self.dict["filename"] = prop
prop = ModeProperty(self.config.get(sectname, "mode"))
self.dict["mode"] = prop
self.propnames.extend(["filename", "mode"])
class RotatingFileHandlerProxy(FileHandlerProxy):
def __init__(self, config, dict):
FileHandlerProxy.__init__(self, config, dict)
prop = MaxSizeProperty(dict.get("maxsize", "0"))
self.dict["maxsize"] = prop
prop = BackupCountProperty(dict.get("backcount", "1"))
self.dict["backcount"] = prop
self.propnames.extend(["maxsize", "backcount"])
def writeConfig(self, file):
HandlerProxy.writeConfig(self, file)
fn = self.getPropValue("filename")
file.write("filename=%s\n" % fn)
mode = self.getPropValue("mode")
file.write("mode=%s\n" % mode)
ms = self.getPropValue("maxsize")
file.write("maxsize=%s\n" % ms)
bc = self.getPropValue("backcount")
file.write("backcount=%s\n" % bc)
file.write("args=('%s', '%s', %s, %s)\n\n" % (fn, mode, ms, bc))
def readConfig(self, sectname):
FileHandlerProxy.readConfig(self, sectname)
prop = MaxSizeProperty(self.config.get(sectname, "maxsize"))
self.dict["maxsize"] = prop
prop = BackupCountProperty(self.config.get(sectname, "backcount"))
self.dict["backcount"] = prop
self.propnames.extend(["maxsize", "backcount"])
class HostProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "host", "Host", value)
class PortProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "port", "Port", value)
class SocketHandlerProxy(HandlerProxy):
def __init__(self, config, dict):
HandlerProxy.__init__(self, config, dict)
prop = HostProperty(dict.get("host", "localhost"))
self.dict["host"] = prop
prop = PortProperty(dict.get("port", "handlers.DEFAULT_TCP_LOGGING_PORT"))
self.dict["port"] = prop
self.propnames.extend(["host", "port"])
def writeConfig(self, file):
HandlerProxy.writeConfig(self, file)
host = self.getPropValue("host")
file.write("host=%s\n" % host)
port = self.getPropValue("port")
file.write("port=%s\n" % port)
file.write("args=('%s', %s)\n\n" % (host, port))
def readConfig(self, sectname):
prop = HostProperty(self.config.get(sectname, "host"))
self.dict["host"] = prop
prop = PortProperty(self.config.get(sectname, "port"))
self.dict["port"] = prop
self.propnames.extend(["host", "port"])
class DatagramHandlerProxy(HandlerProxy):
def __init__(self, config, dict):
HandlerProxy.__init__(self, config, dict)
prop = HostProperty(dict.get("host", "localhost"))
self.dict["host"] = prop
prop = PortProperty(dict.get("port", "handlers.DEFAULT_UDP_LOGGING_PORT"))
self.dict["port"] = prop
self.propnames.extend(["host", "port"])
def writeConfig(self, file):
HandlerProxy.writeConfig(self, file)
host = self.getPropValue("host")
file.write("host=%s\n" % host)
port = self.getPropValue("port")
file.write("port=%s\n" % port)
file.write("args=('%s', %s)\n\n" % (host, port))
def readConfig(self, sectname):
prop = HostProperty(self.config.get(sectname, "host"))
self.dict["host"] = prop
prop = PortProperty(self.config.get(sectname, "port"))
self.dict["port"] = prop
self.propnames.extend(["host", "port"])
class URLProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "url", "URL", value)
class MethodProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "method", "HTTP Method", value)
def getChoices(self):
return HTTP_METHODS
class HTTPHandlerProxy(HandlerProxy):
def __init__(self, config, dict):
HandlerProxy.__init__(self, config, dict)
prop = HostProperty(dict.get("host", "localhost"))
self.dict["host"] = prop
prop = PortProperty(dict.get("port", "80"))
self.dict["port"] = prop
prop = URLProperty(dict.get("url", ""))
self.dict["url"] = prop
prop = MethodProperty(dict.get("method", "GET"))
self.dict["method"] = prop
self.propnames.extend(["host", "port", "url", "method"])
def writeConfig(self, file):
HandlerProxy.writeConfig(self, file)
host = self.getPropValue("host")
file.write("host=%s\n" % host)
port = self.getPropValue("port")
file.write("port=%s\n" % port)
url = self.getPropValue("url")
file.write("url=%s\n" % url)
meth = self.getPropValue("method")
file.write("method=%s\n" % meth)
file.write("args=('%s:%s', '%s', '%s')\n\n" % (host, port, url, meth))
def readConfig(self, sectname):
prop = HostProperty(self.config.get(sectname, "host"))
self.dict["host"] = prop
prop = PortProperty(self.config.get(sectname, "port"))
self.dict["port"] = prop
prop = URLProperty(self.config.get(sectname, "url"))
self.dict["url"] = prop
prop = MethodProperty(self.config.get(sectname, "method"))
self.dict["method"] = prop
self.propnames.extend(["host", "port", "url", "method"])
class SOAPHandlerProxy(HandlerProxy):
def __init__(self, config, dict):
HandlerProxy.__init__(self, config, dict)
prop = HostProperty(dict.get("host", "localhost"))
self.dict["host"] = prop
prop = PortProperty(dict.get("port", "80"))
self.dict["port"] = prop
prop = URLProperty(dict.get("url", ""))
self.dict["url"] = prop
self.propnames.extend(["host", "port", "url"])
def writeConfig(self, file):
HandlerProxy.writeConfig(self, file)
host = self.getPropValue("host")
file.write("host=%s\n" % host)
port = self.getPropValue("port")
file.write("port=%s\n" % port)
url = self.getPropValue("url")
file.write("url=%s\n" % url)
file.write("args=('%s:%s', '%s')\n\n" % (host, port, url))
def readConfig(self, sectname):
prop = HostProperty(self.config.get(sectname, "host"))
self.dict["host"] = prop
prop = PortProperty(self.config.get(sectname, "port"))
self.dict["port"] = prop
prop = URLProperty(self.config.get(sectname, "url"))
self.dict["url"] = prop
self.propnames.extend(["host", "port", "url"])
class FacilityProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "facility", "Facility", value)
def getChoices(self):
return SYSLOG_FACILITIES
class SysLogHandlerProxy(HandlerProxy):
def __init__(self, config, dict):
HandlerProxy.__init__(self, config, dict)
prop = HostProperty(dict.get("host", "localhost"))
self.dict["host"] = prop
prop = PortProperty(dict.get("port", "handlers.SYSLOG_UDP_PORT"))
self.dict["port"] = prop
prop = FacilityProperty(dict.get("facility", "handlers.SysLogHandler.LOG_USER"))
self.dict["facility"] = prop
self.propnames.extend(["host", "port", "facility"])
def writeConfig(self, file):
HandlerProxy.writeConfig(self, file)
host = self.getPropValue("host")
file.write("host=%s\n" % host)
port = self.getPropValue("port")
file.write("port=%s\n" % port)
fac = self.getPropValue("facility")
file.write("facility=%s\n" % fac)
file.write("args=(('%s', %s), handlers.SysLogHandler.%s)\n\n" % (host, port, fac))
def readConfig(self, sectname):
prop = HostProperty(self.config.get(sectname, "host"))
self.dict["host"] = prop
prop = PortProperty(self.config.get(sectname, "port"))
self.dict["port"] = prop
prop = FacilityProperty(self.config.get(sectname, "facility"))
self.dict["facility"] = prop
self.propnames.extend(["host", "port", "facility"])
class FromProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "from", "From", value)
class ToProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "to", "To", value)
class SubjectProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "subject", "Subject", value)
class SMTPHandlerProxy(HandlerProxy):
def __init__(self, config, dict):
HandlerProxy.__init__(self, config, dict)
prop = HostProperty(dict.get("host", "localhost"))
self.dict["host"] = prop
prop = PortProperty(dict.get("port", "25"))
self.dict["port"] = prop
prop = FromProperty(dict.get("from", ""))
self.dict["from"] = prop
prop = ToProperty(dict.get("to", ""))
self.dict["to"] = prop
prop = SubjectProperty(dict.get("subject", ""))
self.dict["subject"] = prop
self.propnames.extend(["host", "port", "from", "to", "subject"])
def writeConfig(self, file):
HandlerProxy.writeConfig(self, file)
host = self.getPropValue("host")
file.write("host=%s\n" % host)
port = self.getPropValue("port")
file.write("port=%s\n" % port)
frm = self.getPropValue("from")
file.write("from=%s\n" % frm)
to = self.getPropValue("to")
file.write("to=%s\n" % to)
subj = self.getPropValue("subject")
file.write("subject=%s\n" % subj)
to = string.split(to, ",")
file.write("args=('%s', '%s', %s, '%s')\n\n" % (host, frm, repr(to), subj))
def readConfig(self, sectname):
prop = HostProperty(self.config.get(sectname, "host"))
self.dict["host"] = prop
prop = PortProperty(self.config.get(sectname, "port"))
self.dict["port"] = prop
prop = FromProperty(self.config.get(sectname, "from"))
self.dict["from"] = prop
prop = ToProperty(self.config.get(sectname, "to"))
self.dict["to"] = prop
prop = SubjectProperty(self.config.get(sectname, "subject"))
self.dict["subject"] = prop
self.propnames.extend(["host", "port", "from", "to", "subject"])
class CapacityProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "capacity", "Capacity", value)
class FlushLevelProperty(LevelProperty):
def __init__(self, value=None):
Property.__init__(self, "flushlevel", "Flush Level", value)
class TargetProperty(Property):
def __init__(self, config, value=None):
self.config = config
Property.__init__(self, "target", "Target", value)
def getChoices(self):
handlers = self.config.getHandlerChoice()
nm = self.dict["name"].getValueText()
#can't be own target...
return filter(lambda x,nm=nm: x[0] != nm, handlers)
class MemoryHandlerProxy(HandlerProxy):
def __init__(self, config, dict):
HandlerProxy.__init__(self, config, dict)
prop = CapacityProperty(dict.get("capacity", "10"))
self.dict["capacity"] = prop
prop = FlushLevelProperty(dict.get("flushlevel", "ERROR"))
self.dict["flushlevel"] = prop
prop = TargetProperty(config, dict.get("target", ""))
prop.dict = self.dict
self.dict["target"] = prop
self.propnames.extend(["capacity", "flushlevel", "target"])
def writeConfig(self, file):
HandlerProxy.writeConfig(self, file)
cap = self.getPropValue("capacity")
file.write("capacity=%s\n" % cap)
flvl = self.getPropValue("flushlevel")
file.write("flushlevel=%s\n" % flvl)
file.write("target=%s\n" % self.getPropValue("target"))
file.write("args=(%s, %s)\n\n" % (cap, flvl))
def readConfig(self, sectname):
prop = CapacityProperty(self.config.get(sectname, "capacity"))
self.dict["capacity"] = prop
prop = FlushLevelProperty(self.config.get(sectname, "flushlevel"))
self.dict["flushlevel"] = prop
prop = TargetProperty(self.config, self.config.get(sectname, "target"))
prop.dict = self.dict
self.dict["target"] = prop
self.propnames.extend(["capacity", "flushlevel", "target"])
class AppNameProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "appname", "Application Name", value)
class DLLNameProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "dllname", "Message DLL name", value)
class LogTypeProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "logtype", "Log Type", value)
def getChoices(self):
return LOG_TYPES
class NTEventLogHandlerProxy(HandlerProxy):
def __init__(self, config, dict):
HandlerProxy.__init__(self, config, dict)
prop = AppNameProperty(dict.get("appname", "Python Application"))
self.dict["appname"] = prop
prop = DLLNameProperty(dict.get("dllname", ""))
self.dict["dllname"] = prop
prop = LogTypeProperty(dict.get("logtype", "Application"))
self.dict["logtype"] = prop
self.propnames.extend(["appname", "dllname", "logtype"])
def writeConfig(self, file):
HandlerProxy.writeConfig(self, file)
app = self.getPropValue("appname")
file.write("appname=%s\n" % app)
dll = self.getPropValue("dllname")
file.write("dllname=%s\n" % dll)
ltype = self.getPropValue("logtype")
file.write("logtype=%s\n" % ltype)
file.write("args=('%s', '%s', '%s')\n\n" % (app, dll, ltype))
def readConfig(self, sectname):
prop = AppNameProperty(self.config.get(sectname, "appname"))
self.dict["appname"] = prop
prop = DLLNameProperty(self.config.get(sectname, "dllname"))
self.dict["dllname"] = prop
prop = LogTypeProperty(self.config.get(sectname, "logtype"))
self.dict["logtype"] = prop
self.propnames.extend(["appname", "dllname", "logtype"])
# -- logger properties and proxies
class ChannelProperty(Property):
def __init__(self, value=None):
Property.__init__(self, "channel", "Name", value)
class HandlerProperty(Property):
def __init__(self, config, value=None):
self.config = config
Property.__init__(self, "handler", "Handlers", value)
def getChoices(self):
return self.config.getHandlerChoice()
class FilterProperty(Property):
def __init__(self, config, value=None):
self.config = config
Property.__init__(self, "filter", "Filters", value)
def getChoices(self):
return self.config.getFilterChoice()
class ParentProperty(Property):
def __init__(self, config, value=None):
self.config = config
Property.__init__(self, "parent", "Parent", value)
def getChoices(self):
loggers = self.config.getLoggerChoice()
nm = self.dict["name"].getValueText()
#can't be own parent...
return filter(lambda x,nm=nm: x[0] != nm, loggers)
def getValueText(self):
if self.dict.has_key("root"):
return ""
pn = Property.getValueText(self)
rv = ""
while pn != "(root)":
parent = self.config.getLogger(pn)
rv = parent.getPropValue("channel") + "." + rv
pn = parent.getProp("parent").value
return rv[:-1]
class PropagateProperty(Property):
def __init__(self, config, value=None):
self.config = config
Property.__init__(self, "propagate", "Propagate", value)
def getChoices(self):
return BOOLEAN_VALUES
class LoggerProxy(PropertyHolder):
def __init__(self, config, dict):
self.config = config
PropertyHolder.__init__(self, dict)
prop = ChannelProperty(dict.get("channel", ""))
self.dict["channel"] = prop
prop = NameProperty(dict.get("name", ""))
self.dict["name"] = prop
prop = HandlerProperty(config, dict.get("handler", []))
self.dict["handler"] = prop
prop = LevelProperty(dict.get("level", "NOTSET"))
self.dict["level"] = prop
prop = PropagateProperty(self.config, dict.get("propagate", "1"))
self.dict["propagate"] = prop
prop = ParentProperty(config, dict.get("parent", "(root)"))
prop.dict = self.dict
self.dict["parent"] = prop
self.propnames = ["parent", "channel", "level", "propagate", "handler"]
self.onChannelChanged = None
self.deleted = 0
def isReadonly(self, name):
return (name in ["channel", "parent", "propagate"]) and self.dict.has_key("root")
def getQualifiedName(self):
pt = self.getProp("parent").getValueText()
nm = self.getPropValue("channel")
if pt:
pn = pt + "." + nm
else:
pn = nm
if pn == "":
pn = "(root)"
return pn
def setPropValue(self, name, value):
PropertyHolder.setPropValue(self, name, value)
if (name == "channel"):
nm = self.getPropValue("name")
if self.onChannelChanged:
self.onChannelChanged(nm, value)
def writeConfig(self, file):
if self.dict.has_key("root"):
name = "root"
else:
name = self.getPropValue("name")
file.write("[logger_%s]\n" % name)
file.write("level=%s\n" % self.getPropValue("level"))
file.write("propagate=%s\n" % self.getPropValue("propagate"))
file.write("channel=%s\n" % self.getPropValue("channel"))
file.write("parent=%s\n" % self.getPropValue("parent"))
file.write("qualname=%s\n" % self.getQualifiedName())
file.write("handlers=%s\n\n" % string.join(self.getPropValue("handler"), ","))
# -- logging configuration
class LoggingConfig(ConfigParser.ConfigParser):
def __init__(self, defaults=None):
ConfigParser.ConfigParser.__init__(self, defaults)
self.formatters = {}
self.handlers = {}
self.loggers = {}
# self.filters = {}
#create root logger
d = { "name": "(root)", "root": 1, "parent": "" }
self.loggers["(root)"] = LoggerProxy(self, d)
def read(self, fn):
ConfigParser.ConfigParser.read(self, fn)
llist = self.get("loggers", "keys")
llist = string.split(llist, ",")
llist.remove("root")
sectname = "logger_root"
log = self.loggers["(root)"]
log.setPropValue("level", self.get(sectname, "level"))
hlist = self.get(sectname, "handlers")
hlist = string.split(hlist, ",")
log.setPropValue("handler", hlist)
for log in llist:
sectname = "logger_%s" % log
hlist = self.get(sectname, "handlers")
hlist = string.split(hlist, ",")
d = {
"name" : log,
"level" : self.get(sectname, "level"),
"channel" : self.get(sectname, "channel"),
"parent" : self.get(sectname, "parent"),
"propagate" : self.get(sectname, "propagate"),
"handler" : hlist,
}
self.loggers[log] = LoggerProxy(self, d)
hlist = self.get("handlers", "keys")
if len(hlist):
hlist = string.split(hlist, ",")
for hand in hlist:
sectname = "handler_%s" % hand
klass = self.get(sectname, "class")
if klass[:9] == "handlers.":
klass = klass[9:]
d = {
"name" : hand,
"class" : "%sProxy" % klass,
"level" : self.get(sectname, "level"),
"formatter" : self.get(sectname, "formatter"),
}
hobj = HandlerProxy(self, d)
hobj.__class__ = eval("%sProxy" % klass)
hobj.readConfig(sectname)
self.handlers[hand] = hobj
flist = self.get("formatters", "keys")
if len(flist):
flist = string.split(flist, ",")
for form in flist:
sectname = "formatter_%s" % form
d = {
"name" : form,
"format" : self.get(sectname, "format", 1),
"datefmt" : self.get(sectname, "datefmt", 1),
}
self.formatters[form] = FormatterProxy(self, d)
# flist = self.get("filters", "keys")
# if len(flist):
# flist = string.split(flist, ",")
# for filt in flist:
# sectname = "filter_%s" % filt
# d = {
# "name" : filt,
# "lname" : self.get(sectname, "lname", 1),
# }
# self.filters[filt] = FilterProxy(self, d)
def getFormatter(self, name):
if name:
fmt = self.formatters[name]
else:
n = len(self.formatters.keys()) + 1
name = "form%02d" % n
fmt = FormatterProxy(self, {"name": name})
self.formatters[name] = fmt
return fmt
def getHandler(self, name):
if name:
hand = self.handlers[name]
else:
n = len(self.handlers.keys()) + 1
name = "hand%02d" % n
hand = StreamHandlerProxy(self, {"name": name})
self.handlers[name] = hand
return hand
def getLogger(self, name):
if name:
log = self.loggers[name]
else:
n = len(self.loggers.keys()) + 1
name = "log%02d" % n
log = LoggerProxy(self, {"name": name, "channel": name})
self.loggers[name] = log
return log
def getFormatterChoice(self):
values = []
keys = self.formatters.keys()
keys.sort()
for f in keys:
values.append((f, f))
return tuple(values)
def getHandlerChoice(self):
values = []
keys = self.handlers.keys()
keys.sort()
for f in keys:
values.append((f, f))
return tuple(values)
def getFilterChoice(self):
values = []
keys = self.filters.keys()
keys.sort()
for f in keys:
values.append((f, f))
return tuple(values)
def getLoggerChoice(self):
values = []
keys = self.loggers.keys()
keys.sort()
for f in keys:
values.append((f, f))
return tuple(values)
def getLoggers(self):
return self.loggers.values()
def getHandlers(self):
return self.handlers.values()
def getFormatters(self):
return self.formatters.values()
def formatterIsUsed(self, name):
rv = None
for h in self.handlers.keys():
if self.handlers[h].getPropValue("formatter") == name:
rv = h
break
return rv
def handlerIsUsed(self, name):
rv = None
for log in self.loggers.keys():
if name in self.loggers[log].getPropValue("handler"):
rv = log
break
return rv
def removeFormatter(self, name):
del self.formatters[name]
def removeHandler(self, name):
del self.handlers[name]
def removeLogger(self, name):
del self.loggers[name]
def save(self, fn):
#needed because 1.5.2 ConfigParser should be supported
file = open(fn, "w")
#Write out the keys
loggers = self.loggers.keys()
loggers.remove("(root)")
loggers = filter(lambda x, d=self.loggers: not d[x].deleted, loggers)
loggers.sort()
list = ["root"]
list.extend(loggers)
file.write("[loggers]\nkeys=%s\n\n" % string.join(list, ","))
handlers = self.handlers.keys()
handlers.sort()
file.write("[handlers]\nkeys=%s\n\n" % string.join(handlers, ","))
formatters = self.formatters.keys()
formatters.sort()
file.write("[formatters]\nkeys=%s\n\n" % string.join(formatters, ","))
#write out the root logger properties
log = self.loggers["(root)"]
log.writeConfig(file)
#write out other logger properties
for log in loggers:
log = self.loggers[log]
log.writeConfig(file)
#write out handler properties
for hand in handlers:
hand = self.handlers[hand]
hand.writeConfig(file)
#write out formatter properties
for form in formatters:
form = self.formatters[form]
form.writeConfig(file)
file.close()
root = None
def onClose():
if _popup:
_popup.withdraw()
root.destroy()
def main():
global root
root=Tk()
cfg = Configurator(root)
cfg.pack(side=LEFT, fill=BOTH, expand=1)
root.protocol("WM_DELETE_WINDOW", onClose)
root.mainloop()
if __name__ == "__main__":
main()
|