#!/usr/bin/env python # # Copyright 2001-2002 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 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 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('', 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('', 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('', self.onEnter) self.bind('', self.onClick) self.bind('', 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('', 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('', 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('', 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('', 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()