summaryrefslogtreecommitdiff
path: root/Mailman/Logging
diff options
context:
space:
mode:
authorbwarsaw2006-04-17 04:08:17 +0000
committerbwarsaw2006-04-17 04:08:17 +0000
commit0ed815a216c7bb6f820cfdf99fc8d31bcfd19fc0 (patch)
tree7b710a785331abfe28b5b46a7695e6cbd81b7794 /Mailman/Logging
parent9934c9b2b0e76a0b77b7869ecf68cd960d4d5bd7 (diff)
downloadmailman-0ed815a216c7bb6f820cfdf99fc8d31bcfd19fc0.tar.gz
mailman-0ed815a216c7bb6f820cfdf99fc8d31bcfd19fc0.tar.zst
mailman-0ed815a216c7bb6f820cfdf99fc8d31bcfd19fc0.zip
- Convert all logging to Python's standard logging module. Get rid of all
traces of our crufty old Syslog. Most of this work was purely mechanical, except for: 1) Initializing the loggers. For this, there's a new module Mailman/loginit.py (yes all modules from now on will use PEP 8 names). We can't call this 'logging.py' because that will interfere with importing the stdlib module of the same name (can you say Python 2.5 and absolute imports?). If you want to write log messages both to the log file and to stderr, pass True to loginit.initialize(). This will turn on propagation of log messages to the parent 'mailman' logger, which is set up to print to stderr. This is how bin/qrunner works when not running as a subprocess of mailmanctl. 2) The driver script. I had to untwist the StampedLogger stuff and implement differently printing exceptions and such to log/error because standard logging objects don't have a write() method. So we write to a cStringIO and then pass that to the logger. 3) SMTPDirect.py because of the configurability of the log messages. This required changing SafeDict into a dict subclass (which is better than using UserDicts anyway -- yay Python 2.3!). It's probably still possible to flummox things up if you change the name of the loggers in the SMTP_LOG_* variables in mm_cfg.py. However, the worst you can do is cause output to go to stderr and not go to a log file. Note too that all entry points into the Mailman system must call Mailman.loginit.initialize() or the log output will go to stderr (which may occasionally be what you want). Currently all CGIs and qrunners should be working properly. I wish I could have tested all code paths that touch the logger, but that's infeasible. I have tested this, but it's possible that there were some mistakes in the translation. - Mailman.Bouncers.BounceAPI.Stop is a singleton, but not a class instance any more. - True/False code cleanup, PEP 8 import restructuring, whitespace normalization, and copyright year updates, as appropriate.
Diffstat (limited to 'Mailman/Logging')
-rw-r--r--Mailman/Logging/Logger.py104
-rw-r--r--Mailman/Logging/Makefile.in70
-rw-r--r--Mailman/Logging/MultiLogger.py76
-rw-r--r--Mailman/Logging/StampedLogger.py89
-rw-r--r--Mailman/Logging/Syslog.py76
-rw-r--r--Mailman/Logging/Utils.py52
-rw-r--r--Mailman/Logging/__init__.py15
7 files changed, 0 insertions, 482 deletions
diff --git a/Mailman/Logging/Logger.py b/Mailman/Logging/Logger.py
deleted file mode 100644
index 617347d49..000000000
--- a/Mailman/Logging/Logger.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# Copyright (C) 1998-2005 by the Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-# USA.
-
-"""File-based logger, writes to named category files in mm_cfg.LOG_DIR."""
-
-import sys
-import os
-import codecs
-from types import StringType
-
-from Mailman import mm_cfg
-from Mailman.Logging.Utils import _logexc
-
-# Set this to the encoding to be used for your log file output. If set to
-# None, then it uses your system's default encoding. Otherwise, it must be an
-# encoding string appropriate for codecs.open().
-LOG_ENCODING = 'iso-8859-1'
-
-
-
-class Logger:
- def __init__(self, category, nofail=1, immediate=0):
- """nofail says to fallback to sys.__stderr__ if write fails to
- category file - a complaint message is emitted, but no exception is
- raised. Set nofail=0 if you want to handle the error in your code,
- instead.
-
- immediate=1 says to create the log file on instantiation.
- Otherwise, the file is created only when there are writes pending.
- """
- self.__filename = os.path.join(mm_cfg.LOG_DIR, category)
- self.__fp = None
- self.__nofail = nofail
- self.__encoding = LOG_ENCODING or sys.getdefaultencoding()
- if immediate:
- self.__get_f()
-
- def __del__(self):
- self.close()
-
- def __repr__(self):
- return '<%s to %s>' % (self.__class__.__name__, `self.__filename`)
-
- def __get_f(self):
- if self.__fp:
- return self.__fp
- else:
- try:
- ou = os.umask(002)
- try:
- try:
- f = codecs.open(
- self.__filename, 'a+', self.__encoding, 'replace',
- 1)
- except LookupError:
- f = open(self.__filename, 'a+', 1)
- self.__fp = f
- finally:
- os.umask(ou)
- except IOError, e:
- if self.__nofail:
- _logexc(self, e)
- f = self.__fp = sys.__stderr__
- else:
- raise
- return f
-
- def flush(self):
- f = self.__get_f()
- if hasattr(f, 'flush'):
- f.flush()
-
- def write(self, msg):
- if isinstance(msg, StringType):
- msg = unicode(msg, self.__encoding, 'replace')
- f = self.__get_f()
- try:
- f.write(msg)
- except IOError, msg:
- _logexc(self, msg)
-
- def writelines(self, lines):
- for l in lines:
- self.write(l)
-
- def close(self):
- if not self.__fp:
- return
- self.__get_f().close()
- self.__fp = None
diff --git a/Mailman/Logging/Makefile.in b/Mailman/Logging/Makefile.in
deleted file mode 100644
index e185775fc..000000000
--- a/Mailman/Logging/Makefile.in
+++ /dev/null
@@ -1,70 +0,0 @@
-# Copyright (C) 1998-2003 by the Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-# NOTE: Makefile.in is converted into Makefile by the configure script
-# in the parent directory. Once configure has run, you can recreate
-# the Makefile by running just config.status.
-
-# Variables set by configure
-
-VPATH= @srcdir@
-srcdir= @srcdir@
-bindir= @bindir@
-prefix= @prefix@
-exec_prefix= @exec_prefix@
-DESTDIR=
-
-CC= @CC@
-CHMOD= @CHMOD@
-INSTALL= @INSTALL@
-
-DEFS= @DEFS@
-
-# Customizable but not set by configure
-
-OPT= @OPT@
-CFLAGS= $(OPT) $(DEFS)
-PACKAGEDIR= $(prefix)/Mailman/Logging
-SHELL= /bin/sh
-
-MODULES= *.py
-
-# Modes for directories and executables created by the install
-# process. Default to group-writable directories but
-# user-only-writable for executables.
-DIRMODE= 775
-EXEMODE= 755
-FILEMODE= 644
-INSTALL_PROGRAM=$(INSTALL) -m $(EXEMODE)
-
-
-# Rules
-
-all:
-
-install:
- for f in $(MODULES); \
- do \
- $(INSTALL) -m $(FILEMODE) $(srcdir)/$$f $(DESTDIR)$(PACKAGEDIR); \
- done
-
-finish:
-
-clean:
-
-distclean:
- -rm *.pyc
- -rm Makefile
diff --git a/Mailman/Logging/MultiLogger.py b/Mailman/Logging/MultiLogger.py
deleted file mode 100644
index 7d9435e90..000000000
--- a/Mailman/Logging/MultiLogger.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-"""A mutiple sink logger. Any message written goes to all sub-loggers."""
-
-import sys
-from Mailman.Logging.Utils import _logexc
-
-
-
-class MultiLogger:
- def __init__(self, *args):
- self.__loggers = []
- for logger in args:
- self.__loggers.append(logger)
-
- def add_logger(self, logger):
- if logger not in self.__loggers:
- self.__loggers.append(logger)
-
- def del_logger(self, logger):
- if logger in self.__loggers:
- self.__loggers.remove(logger)
-
- def write(self, msg):
- for logger in self.__loggers:
- # you want to be sure that a bug in one logger doesn't prevent
- # logging to all the other loggers
- try:
- logger.write(msg)
- except:
- _logexc(logger, msg)
-
- def writelines(self, lines):
- for line in lines:
- self.write(line)
-
- def flush(self):
- for logger in self.__loggers:
- if hasattr(logger, 'flush'):
- # you want to be sure that a bug in one logger doesn't prevent
- # logging to all the other loggers
- try:
- logger.flush()
- except:
- _logexc(logger)
-
- def close(self):
- for logger in self.__loggers:
- # you want to be sure that a bug in one logger doesn't prevent
- # logging to all the other loggers
- try:
- if logger <> sys.__stderr__ and logger <> sys.__stdout__:
- logger.close()
- except:
- _logexc(logger)
-
- def reprime(self):
- for logger in self.__loggers:
- try:
- logger.reprime()
- except AttributeError:
- pass
diff --git a/Mailman/Logging/StampedLogger.py b/Mailman/Logging/StampedLogger.py
deleted file mode 100644
index ca313c537..000000000
--- a/Mailman/Logging/StampedLogger.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-import os
-import time
-
-from Mailman.Logging.Logger import Logger
-
-
-
-class StampedLogger(Logger):
- """Record messages in log files, including date stamp and optional label.
-
- If manual_reprime is on (off by default), then timestamp prefix will
- included only on first .write() and on any write immediately following a
- call to the .reprime() method. This is useful for when StampedLogger is
- substituting for sys.stderr, where you'd like to see the grouping of
- multiple writes under a single timestamp (and there is often is one group,
- for uncaught exceptions where a script is bombing).
-
- In any case, the identifying prefix will only follow writes that start on
- a new line.
-
- Nofail (by default) says to fallback to sys.stderr if write fails to
- category file. A message is emitted, but the IOError is caught.
- Initialize with nofail=0 if you want to handle the error in your code,
- instead.
-
- """
- def __init__(self, category, label=None, manual_reprime=0, nofail=1,
- immediate=1):
- """If specified, optional label is included after timestamp.
- Other options are passed to the Logger class initializer.
- """
- self.__label = label
- self.__manual_reprime = manual_reprime
- self.__primed = 1
- self.__bol = 1
- Logger.__init__(self, category, nofail, immediate)
-
- def reprime(self):
- """Reset so timestamp will be included with next write."""
- self.__primed = 1
-
- def write(self, msg):
- if not self.__bol:
- prefix = ""
- else:
- if not self.__manual_reprime or self.__primed:
- stamp = time.strftime("%b %d %H:%M:%S %Y ",
- time.localtime(time.time()))
- self.__primed = 0
- else:
- stamp = ""
- if self.__label is None:
- label = "(%d)" % os.getpid()
- else:
- label = "%s(%d):" % (self.__label, os.getpid())
- prefix = stamp + label
- Logger.write(self, "%s %s" % (prefix, msg))
- if msg and msg[-1] == '\n':
- self.__bol = 1
- else:
- self.__bol = 0
-
- def writelines(self, lines):
- first = 1
- for l in lines:
- if first:
- self.write(l)
- first = 0
- else:
- if l and l[0] not in [' ', '\t', '\n']:
- Logger.write(self, ' ' + l)
- else:
- Logger.write(self, l)
diff --git a/Mailman/Logging/Syslog.py b/Mailman/Logging/Syslog.py
deleted file mode 100644
index 531ab1d7b..000000000
--- a/Mailman/Logging/Syslog.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# Copyright (C) 1998-2005 by the Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-# USA.
-
-"""Central logging class for the Mailman system.
-
-This might eventually be replaced by a syslog based logger, hence the name.
-"""
-
-import quopri
-
-from Mailman.Logging.StampedLogger import StampedLogger
-
-
-
-# Global, shared logger instance. All clients should use this object.
-syslog = None
-
-
-
-# Don't instantiate except below.
-class _Syslog:
- def __init__(self):
- self._logfiles = {}
-
- def __del__(self):
- self.close()
-
- def write(self, kind, msg, *args, **kws):
- self.write_ex(kind, msg, args, kws)
-
- # We need this because SMTPDirect tries to pass in a special dict-like
- # object, which is not a concrete dictionary. This is not allowed by
- # Python's extended call syntax. :(
- def write_ex(self, kind, msg, args=None, kws=None):
- origmsg = msg
- logf = self._logfiles.get(kind)
- if not logf:
- logf = self._logfiles[kind] = StampedLogger(kind)
- try:
- if args:
- msg %= args
- if kws:
- msg %= kws
- # It's really bad if exceptions in the syslogger cause other crashes
- except Exception, e:
- msg = 'Bad format "%s": %s: %s' % (origmsg, repr(e), e)
- try:
- logf.write(msg + '\n')
- except UnicodeError:
- # Python 2.4 may fail to write 8bit (non-ascii) characters
- logf.write(quopri.encodestring(msg) + '\n')
-
- # For the ultimate in convenience
- __call__ = write
-
- def close(self):
- for kind, logger in self._logfiles.items():
- logger.close()
- self._logfiles.clear()
-
-
-syslog = _Syslog()
diff --git a/Mailman/Logging/Utils.py b/Mailman/Logging/Utils.py
deleted file mode 100644
index 46bf487af..000000000
--- a/Mailman/Logging/Utils.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-import sys
-import traceback
-
-
-def _logexc(logger=None, msg=''):
- sys.__stderr__.write('Logging error: %s\n' % logger)
- traceback.print_exc(file=sys.__stderr__)
- sys.__stderr__.write('Original log message:\n%s\n' % msg)
-
-
-def LogStdErr(category, label, manual_reprime=1, tee_to_real_stderr=1):
- """Establish a StampedLogger on sys.stderr if possible.
-
- If tee_to_real_stderr is true, then the real standard error also gets
- output, via a MultiLogger.
-
- Returns the MultiLogger if successful, None otherwise.
- """
- from StampedLogger import StampedLogger
- from MultiLogger import MultiLogger
- try:
- logger = StampedLogger(category,
- label=label,
- manual_reprime=manual_reprime,
- nofail=0)
- if tee_to_real_stderr:
- if hasattr(sys, '__stderr__'):
- stderr = sys.__stderr__
- else:
- stderr = sys.stderr
- logger = MultiLogger(stderr, logger)
- sys.stderr = logger
- return sys.stderr
- except IOError:
- return None
-
diff --git a/Mailman/Logging/__init__.py b/Mailman/Logging/__init__.py
deleted file mode 100644
index f569e43f4..000000000
--- a/Mailman/Logging/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.