SF patch #687683, Patches to logging (updates from Vinay)

Mostly rename WARN -> WARNING
Other misc tweaks
Update tests (not in original patch)
diff --git a/Doc/lib/liblogging.tex b/Doc/lib/liblogging.tex
index 00c6e84..dd65f3b 100644
--- a/Doc/lib/liblogging.tex
+++ b/Doc/lib/liblogging.tex
@@ -250,8 +250,9 @@
 \begin{methoddesc}{setLevel}{lvl}
 Sets the threshold for this logger to \var{lvl}. Logging messages
 which are less severe than \var{lvl} will be ignored. When a logger is
-created, the level is set to \constant{ALL} (which causes all messages
-to be processed).
+created, the level is set to \constant{NOTSET} (which causes all messages
+to be processed in the root logger, or delegation to the parent in non-root
+loggers).
 \end{methoddesc}
 
 \begin{methoddesc}{isEnabledFor}{lvl}
@@ -263,9 +264,9 @@
 
 \begin{methoddesc}{getEffectiveLevel}{}
 Indicates the effective level for this logger. If a value other than
-\constant{ALL} has been set using \method{setLevel()}, it is returned.
+\constant{NOTSET} has been set using \method{setLevel()}, it is returned.
 Otherwise, the hierarchy is traversed towards the root until a value
-other than \constant{ALL} is found, and that value is returned.
+other than \constant{NOTSET} is found,and that value is returned.
 \end{methoddesc}
 
 \begin{methoddesc}{debug}{msg\optional{, *args\optional{, **kwargs}}}
@@ -355,7 +356,7 @@
 base for more useful subclasses. However, the \method{__init__()}
 method in subclasses needs to call \method{Handler.__init__()}.
 
-\begin{methoddesc}{__init__}{level=\constant{ALL}}
+\begin{methoddesc}{__init__}{level=\constant{NOTSET}}
 Initializes the \class{Handler} instance by setting its level, setting
 the list of filters to the empty list and creating a lock (using
 \method{getLock()}) for serializing access to an I/O mechanism.
@@ -377,7 +378,7 @@
 \begin{methoddesc}{setLevel}{lvl}
 Sets the threshold for this handler to \var{lvl}. Logging messages which are
 less severe than \var{lvl} will be ignored. When a handler is created, the
-level is set to \constant{ALL} (which causes all messages to be processed).
+level is set to \constant{NOTSET} (which causes all messages to be processed).
 \end{methoddesc}
 
 \begin{methoddesc}{setFormatter}{form}
@@ -487,7 +488,7 @@
 The \class{RotatingFileHandler} class supports rotation of disk log files.
 
 \begin{classdesc}{RotatingFileHandler}{filename\optional{, mode, maxBytes,
-							 backupCount}}
+																			 backupCount}}
 Returns a new instance of the \class{RotatingFileHandler} class. The
 specified file is opened and used as the stream for logging. If
 \var{mode} is not specified, \code{'a'} is used. By default, the
@@ -736,7 +737,7 @@
 \end{methoddesc}
 
 \begin{classdesc}{MemoryHandler}{capacity\optional{, flushLevel
-				 \optional{, target}}}
+\optional{, target}}}
 Returns a new instance of the \class{MemoryHandler} class. The
 instance is initialized with a buffer size of \var{capacity}. If
 \var{flushLevel} is not specified, \constant{ERROR} is used. If no
@@ -813,10 +814,10 @@
                      relative to the time the logging module was loaded
                      (typically at application startup time)
 \%(thread)d          Thread ID (if available)
+\%(process)d         Process ID (if available)
 \%(message)s         The result of msg \% args, computed just as the
                      record is emitted
 
-
 \begin{classdesc}{Formatter}{\optional{fmt\optional{, datefmt}}}
 Returns a new instance of the \class{Formatter} class. The
 instance is initialized with a format string for the message as a whole,
@@ -889,7 +890,7 @@
 facilitate extension.
 
 \begin{classdesc}{LogRecord}{name, lvl, pathname, lineno, msg, args,
-			     exc_info}
+														 exc_info}
 Returns an instance of \class{LogRecord} initialized with interesting
 information. The \var{name} is the logger name; \var{lvl} is the
 numeric level; \var{pathname} is the absolute pathname of the source
diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py
index d602b1c..18fe379 100644
--- a/Lib/logging/__init__.py
+++ b/Lib/logging/__init__.py
@@ -36,16 +36,24 @@
 
 __author__  = "Vinay Sajip <vinay_sajip@red-dove.com>"
 __status__  = "alpha"
-__version__ = "0.4.7"
-__date__    = "27 August 2002"
+__version__ = "0.4.8"
+__date__    = "16 February 2003"
 
 #---------------------------------------------------------------------------
 #   Miscellaneous module data
 #---------------------------------------------------------------------------
 
 #
+# _verinfo is used for when behaviour needs to be adjusted to the version
+# of Python
+#
+
+_verinfo = getattr(sys, "version_info", None)
+
+#
 #_srcfile is used when walking the stack to check when we've got the first
 # caller stack frame.
+#
 if string.lower(__file__[-4:]) in ['.pyc', '.pyo']:
     _srcfile = __file__[:-4] + '.py'
 else:
@@ -70,7 +78,6 @@
 #
 raiseExceptions = 1
 
-
 #---------------------------------------------------------------------------
 #   Level related stuff
 #---------------------------------------------------------------------------
@@ -84,7 +91,8 @@
 CRITICAL = 50
 FATAL = CRITICAL
 ERROR = 40
-WARN = 30
+WARNING = 30
+WARN = WARNING
 INFO = 20
 DEBUG = 10
 NOTSET = 0
@@ -92,13 +100,14 @@
 _levelNames = {
     CRITICAL : 'CRITICAL',
     ERROR : 'ERROR',
-    WARN : 'WARN',
+    WARNING : 'WARNING',
     INFO : 'INFO',
     DEBUG : 'DEBUG',
     NOTSET : 'NOTSET',
     'CRITICAL' : CRITICAL,
     'ERROR' : ERROR,
-    'WARN' : WARN,
+    'WARN' : WARNING,
+    'WARNING' : WARNING,
     'INFO' : INFO,
     'DEBUG' : DEBUG,
     'NOTSET' : NOTSET,
@@ -108,7 +117,7 @@
     """
     Return the textual representation of logging level 'level'.
 
-    If the level is one of the predefined levels (CRITICAL, ERROR, WARN,
+    If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
     INFO, DEBUG) then you get the corresponding string. If you have
     associated levels with names using addLevelName then the name you have
     associated with 'level' is returned. Otherwise, the string
@@ -204,6 +213,7 @@
             self.thread = thread.get_ident()
         else:
             self.thread = None
+        self.process = os.getpid()
 
     def __str__(self):
         return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
@@ -216,7 +226,13 @@
         Return the message for this LogRecord after merging any user-supplied
         arguments with the message.
         """
-        msg = str(self.msg)
+        if not hasattr(types, "UnicodeType"): #if no unicode support...
+            msg = str(self.msg)
+        else:
+            try:
+                msg = str(self.msg)
+            except UnicodeError:
+                msg = self.msg      #Defer encoding till later
         if self.args:
             msg = msg % self.args
         return msg
@@ -243,9 +259,9 @@
 
     %(name)s            Name of the logger (logging channel)
     %(levelno)s         Numeric logging level for the message (DEBUG, INFO,
-                        WARN, ERROR, CRITICAL)
+                        WARNING, ERROR, CRITICAL)
     %(levelname)s       Text logging level for the message ("DEBUG", "INFO",
-                        "WARN", "ERROR", "CRITICAL")
+                        "WARNING", "ERROR", "CRITICAL")
     %(pathname)s        Full pathname of the source file where the logging
                         call was issued (if available)
     %(filename)s        Filename portion of pathname
@@ -260,6 +276,7 @@
                         relative to the time the logging module was loaded
                         (typically at application startup time)
     %(thread)d          Thread ID (if available)
+    %(process)d         Process ID (if available)
     %(message)s         The result of record.getMessage(), computed just as
                         the record is emitted
     """
@@ -558,14 +575,17 @@
 
         Emission depends on filters which may have been added to the handler.
         Wrap the actual emission of the record with acquisition/release of
-        the I/O thread lock.
+        the I/O thread lock. Returns whether the filter passed the record for
+        emission.
         """
-        if self.filter(record):
+        rv = self.filter(record)
+        if rv:
             self.acquire()
             try:
                 self.emit(record)
             finally:
                 self.release()
+        return rv
 
     def setFormatter(self, fmt):
         """
@@ -591,17 +611,17 @@
         """
         pass
 
-    def handleError(self):
+    def handleError(self, record):
         """
         Handle errors which occur during an emit() call.
 
         This method should be called from handlers when an exception is
-        encountered during an emit() call. By default it does nothing,
-        because by default raiseExceptions is false, which means that
+        encountered during an emit() call. If raiseExceptions is false,
         exceptions get silently ignored. This is what is mostly wanted
         for a logging system - most users will not care about errors in
         the logging system, they are more interested in application errors.
         You could, however, replace this with a custom handler if you wish.
+        The record which was being processed is passed in to this method.
         """
         if raiseExceptions:
             import traceback
@@ -645,10 +665,16 @@
         """
         try:
             msg = self.format(record)
-            self.stream.write("%s\n" % msg)
+            if not hasattr(types, "UnicodeType"): #if no unicode support...
+                self.stream.write("%s\n" % msg)
+            else:
+                try:
+                    self.stream.write("%s\n" % msg)
+                except UnicodeError:
+                    self.stream.write("%s\n" % msg.encode("UTF-8"))
             self.flush()
         except:
-            self.handleError()
+            self.handleError(record)
 
 class FileHandler(StreamHandler):
     """
@@ -861,19 +887,21 @@
         if INFO >= self.getEffectiveLevel():
             apply(self._log, (INFO, msg, args), kwargs)
 
-    def warn(self, msg, *args, **kwargs):
+    def warning(self, msg, *args, **kwargs):
         """
-        Log 'msg % args' with severity 'WARN'.
+        Log 'msg % args' with severity 'WARNING'.
 
         To pass exception information, use the keyword argument exc_info with
         a true value, e.g.
 
-        logger.warn("Houston, we have a %s", "bit of a problem", exc_info=1)
+        logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
         """
-        if self.manager.disable >= WARN:
+        if self.manager.disable >= WARNING:
             return
-        if self.isEnabledFor(WARN):
-            apply(self._log, (WARN, msg, args), kwargs)
+        if self.isEnabledFor(WARNING):
+            apply(self._log, (WARNING, msg, args), kwargs)
+
+    warn = warning
 
     def error(self, msg, *args, **kwargs):
         """
@@ -982,7 +1010,7 @@
         Remove the specified handler from this logger.
         """
         if hdlr in self.handlers:
-            hdlr.close()
+            #hdlr.close()
             self.handlers.remove(hdlr)
 
     def callHandlers(self, record):
@@ -1047,7 +1075,7 @@
 
 _loggerClass = Logger
 
-root = RootLogger(WARN)
+root = RootLogger(WARNING)
 Logger.root = root
 Logger.manager = Manager(Logger.root)
 
@@ -1119,13 +1147,15 @@
     """
     apply(error, (msg,)+args, {'exc_info': 1})
 
-def warn(msg, *args, **kwargs):
+def warning(msg, *args, **kwargs):
     """
-    Log a message with severity 'WARN' on the root logger.
+    Log a message with severity 'WARNING' on the root logger.
     """
     if len(root.handlers) == 0:
         basicConfig()
-    apply(root.warn, (msg,)+args, kwargs)
+    apply(root.warning, (msg,)+args, kwargs)
+
+warn = warning
 
 def info(msg, *args, **kwargs):
     """
diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py
index bb3fe70..48e14b6 100644
--- a/Lib/logging/handlers.py
+++ b/Lib/logging/handlers.py
@@ -100,7 +100,7 @@
         """
         if self.maxBytes > 0:                   # are we rolling over?
             msg = "%s\n" % self.format(record)
-            #print msg
+            self.stream.seek(0, 2)  #due to non-posix-compliant Windows feature
             if self.stream.tell() + len(msg) >= self.maxBytes:
                 self.doRollover()
         logging.FileHandler.emit(self, record)
@@ -145,8 +145,8 @@
         This function allows for partial sends which can happen when the
         network is busy.
         """
-        v = sys.version_info
-        if v[0] >= 2 and v[1] >= 2:
+        v = logging._verinfo
+        if v and (v[0] >= 2) and (v[1] >= 2):
             self.sock.sendall(s)
         else:
             sentsofar = 0
@@ -167,7 +167,7 @@
         slen = struct.pack(">L", len(s))
         return slen + s
 
-    def handleError(self):
+    def handleError(self, record):
         """
         Handle an error during logging.
 
@@ -179,7 +179,7 @@
             self.sock.close()
             self.sock = None        #try to reconnect next time
         else:
-            logging.Handler.handleError(self)
+            logging.Handler.handleError(self, record)
 
     def emit(self, record):
         """
@@ -196,7 +196,7 @@
                 self.sock = self.makeSocket()
             self.send(s)
         except:
-            self.handleError()
+            self.handleError(record)
 
     def close(self):
         """
@@ -355,7 +355,7 @@
             except socket.error:
                 self.socket.close()
                 self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-                self.socket.connect(address)
+            self.socket.connect(address)
             self.unixsocket = 1
         else:
             self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
@@ -411,7 +411,7 @@
             else:
                 self.socket.sendto(msg, self.address)
         except:
-            self.handleError()
+            self.handleError(record)
 
 class SMTPHandler(logging.Handler):
     """
@@ -434,6 +434,8 @@
             self.mailhost = mailhost
             self.mailport = None
         self.fromaddr = fromaddr
+        if type(toaddrs) == types.StringType:
+            toaddrs = [toaddrs]
         self.toaddrs = toaddrs
         self.subject = subject
 
@@ -467,7 +469,7 @@
             smtp.sendmail(self.fromaddr, self.toaddrs, msg)
             smtp.quit()
         except:
-            self.handleError()
+            self.handleError(record)
 
 class NTEventLogHandler(logging.Handler):
     """
@@ -496,7 +498,7 @@
             self.typemap = {
                 logging.DEBUG   : win32evtlog.EVENTLOG_INFORMATION_TYPE,
                 logging.INFO    : win32evtlog.EVENTLOG_INFORMATION_TYPE,
-                logging.WARN    : win32evtlog.EVENTLOG_WARNING_TYPE,
+                logging.WARNING : win32evtlog.EVENTLOG_WARNING_TYPE,
                 logging.ERROR   : win32evtlog.EVENTLOG_ERROR_TYPE,
                 logging.CRITICAL: win32evtlog.EVENTLOG_ERROR_TYPE,
          }
@@ -531,7 +533,7 @@
         Override this if you want to specify your own types. This version does
         a mapping using the handler's typemap attribute, which is set up in
         __init__() to a dictionary which contains mappings for DEBUG, INFO,
-        WARN, ERROR and CRITICAL. If you are using your own levels you will
+        WARNING, ERROR and CRITICAL. If you are using your own levels you will
         either need to override this method or place a suitable dictionary in
         the handler's typemap attribute.
         """
@@ -552,7 +554,7 @@
                 msg = self.format(record)
                 self._welu.ReportEvent(self.appname, id, cat, type, [msg])
             except:
-                self.handleError()
+                self.handleError(record)
 
     def close(self):
         """
@@ -610,7 +612,7 @@
                 h.send(data)
             h.getreply()    #can't do anything with the result
         except:
-            self.handleError()
+            self.handleError(record)
 
 class BufferingHandler(logging.Handler):
     """
diff --git a/Lib/test/output/test_logging b/Lib/test/output/test_logging
index 3cbbebf..0b0c4a0 100644
--- a/Lib/test/output/test_logging
+++ b/Lib/test/output/test_logging
@@ -4,11 +4,11 @@
 ERROR:ERR:Message 1
 CRITICAL:INF:Message 2
 ERROR:INF:Message 3
-WARN:INF:Message 4
+WARNING:INF:Message 4
 INFO:INF:Message 5
 CRITICAL:INF.UNDEF:Message 6
 ERROR:INF.UNDEF:Message 7
-WARN:INF.UNDEF:Message 8
+WARNING:INF.UNDEF:Message 8
 INFO:INF.UNDEF:Message 9
 CRITICAL:INF.ERR:Message 10
 ERROR:INF.ERR:Message 11
@@ -16,12 +16,12 @@
 ERROR:INF.ERR.UNDEF:Message 13
 CRITICAL:DEB:Message 14
 ERROR:DEB:Message 15
-WARN:DEB:Message 16
+WARNING:DEB:Message 16
 INFO:DEB:Message 17
 DEBUG:DEB:Message 18
 CRITICAL:UNDEF:Message 19
 ERROR:UNDEF:Message 20
-WARN:UNDEF:Message 21
+WARNING:UNDEF:Message 21
 INFO:UNDEF:Message 22
 CRITICAL:INF.BADPARENT.UNDEF:Message 23
 CRITICAL:INF.BADPARENT:Message 24
@@ -259,10 +259,10 @@
 -- log_test2  begin  ---------------------------------------------------
 -- logging at DEBUG, nothing should be seen yet --
 -- logging at INFO, nothing should be seen yet --
--- logging at WARN, 3 messages should be seen --
+-- logging at WARNING, 3 messages should be seen --
 DEBUG:root:Debug message
 INFO:root:Info message
-WARN:root:Warn message
+WARNING:root:Warn message
 -- logging 0 at INFO, messages should be seen every 10 events --
 -- logging 1 at INFO, messages should be seen every 10 events --
 -- logging 2 at INFO, messages should be seen every 10 events --
@@ -490,11 +490,11 @@
 ERR -> ERROR: Message 1 (via logrecv.tcp.ERR)
 INF -> CRITICAL: Message 2 (via logrecv.tcp.INF)
 INF -> ERROR: Message 3 (via logrecv.tcp.INF)
-INF -> WARN: Message 4 (via logrecv.tcp.INF)
+INF -> WARNING: Message 4 (via logrecv.tcp.INF)
 INF -> INFO: Message 5 (via logrecv.tcp.INF)
 INF.UNDEF -> CRITICAL: Message 6 (via logrecv.tcp.INF.UNDEF)
 INF.UNDEF -> ERROR: Message 7 (via logrecv.tcp.INF.UNDEF)
-INF.UNDEF -> WARN: Message 8 (via logrecv.tcp.INF.UNDEF)
+INF.UNDEF -> WARNING: Message 8 (via logrecv.tcp.INF.UNDEF)
 INF.UNDEF -> INFO: Message 9 (via logrecv.tcp.INF.UNDEF)
 INF.ERR -> CRITICAL: Message 10 (via logrecv.tcp.INF.ERR)
 INF.ERR -> ERROR: Message 11 (via logrecv.tcp.INF.ERR)
@@ -502,12 +502,12 @@
 INF.ERR.UNDEF -> ERROR: Message 13 (via logrecv.tcp.INF.ERR.UNDEF)
 DEB -> CRITICAL: Message 14 (via logrecv.tcp.DEB)
 DEB -> ERROR: Message 15 (via logrecv.tcp.DEB)
-DEB -> WARN: Message 16 (via logrecv.tcp.DEB)
+DEB -> WARNING: Message 16 (via logrecv.tcp.DEB)
 DEB -> INFO: Message 17 (via logrecv.tcp.DEB)
 DEB -> DEBUG: Message 18 (via logrecv.tcp.DEB)
 UNDEF -> CRITICAL: Message 19 (via logrecv.tcp.UNDEF)
 UNDEF -> ERROR: Message 20 (via logrecv.tcp.UNDEF)
-UNDEF -> WARN: Message 21 (via logrecv.tcp.UNDEF)
+UNDEF -> WARNING: Message 21 (via logrecv.tcp.UNDEF)
 UNDEF -> INFO: Message 22 (via logrecv.tcp.UNDEF)
 INF.BADPARENT.UNDEF -> CRITICAL: Message 23 (via logrecv.tcp.INF.BADPARENT.UNDEF)
 INF.BADPARENT -> CRITICAL: Message 24 (via logrecv.tcp.INF.BADPARENT)
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index 113df5c..9c47408 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -342,15 +342,16 @@
 def test2():
     logger = logging.getLogger("")
     sh = logger.handlers[0]
+    sh.close()
     logger.removeHandler(sh)
-    mh = logging.handlers.MemoryHandler(10,logging.WARN, sh)
+    mh = logging.handlers.MemoryHandler(10,logging.WARNING, sh)
     logger.setLevel(logging.DEBUG)
     logger.addHandler(mh)
     message("-- logging at DEBUG, nothing should be seen yet --")
     logger.debug("Debug message")
     message("-- logging at INFO, nothing should be seen yet --")
     logger.info("Info message")
-    message("-- logging at WARN, 3 messages should be seen --")
+    message("-- logging at WARNING, 3 messages should be seen --")
     logger.warn("Warn message")
     for i in xrange(102):
         message(MSG % i)
@@ -436,6 +437,7 @@
 
         rootLogger.addHandler(hdlr)
         test0()
+        hdlr.close()
         rootLogger.removeHandler(hdlr)
 
         banner("log_test0", "end")