[Python-checkins] r75310 - in python: branches/py3k/Doc/library/logging.rst branches/py3k/Lib/logging/__init__.py branches/py3k/Lib/logging/config.py branches/py3k/Lib/logging/handlers.py branches/py3k/Misc/NEWS trunk/Doc/library/logging.rst trunk/Lib/logging/__init__.py trunk/Lib/logging/config.py trunk/Lib/logging/handlers.py trunk/Misc/NEWS

vinay.sajip python-checkins at python.org
Sat Oct 10 22:32:36 CEST 2009


Author: vinay.sajip
Date: Sat Oct 10 22:32:36 2009
New Revision: 75310

Log:
Issue #7086: Added TCP support to SysLogHandler and tidied up some anachronisms in the code.

Modified:
   python/branches/py3k/Doc/library/logging.rst
   python/branches/py3k/Lib/logging/__init__.py
   python/branches/py3k/Lib/logging/config.py
   python/branches/py3k/Lib/logging/handlers.py
   python/branches/py3k/Misc/NEWS
   python/trunk/Doc/library/logging.rst
   python/trunk/Lib/logging/__init__.py
   python/trunk/Lib/logging/config.py
   python/trunk/Lib/logging/handlers.py
   python/trunk/Misc/NEWS

Modified: python/branches/py3k/Doc/library/logging.rst
==============================================================================
--- python/branches/py3k/Doc/library/logging.rst	(original)
+++ python/branches/py3k/Doc/library/logging.rst	Sat Oct 10 22:32:36 2009
@@ -763,11 +763,13 @@
 
    Does basic configuration for the logging system by creating a
    :class:`StreamHandler` with a default :class:`Formatter` and adding it to the
-   root logger. The function does nothing if any handlers have been defined for
-   the root logger. The functions :func:`debug`, :func:`info`, :func:`warning`,
+   root logger. The functions :func:`debug`, :func:`info`, :func:`warning`,
    :func:`error` and :func:`critical` will call :func:`basicConfig` automatically
    if no handlers are defined for the root logger.
 
+   This function does nothing if the root logger already has handlers
+   configured for it.
+
    The following keyword arguments are supported.
 
    +--------------+---------------------------------------------+
@@ -1957,16 +1959,22 @@
 supports sending logging messages to a remote or local Unix syslog.
 
 
-.. class:: SysLogHandler(address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER)
+.. class:: SysLogHandler(address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER, socktype=socket.SOCK_DGRAM)
 
    Returns a new instance of the :class:`SysLogHandler` class intended to
    communicate with a remote Unix machine whose address is given by *address* in
    the form of a ``(host, port)`` tuple.  If *address* is not specified,
-   ``('localhost', 514)`` is used.  The address is used to open a UDP socket.  An
+   ``('localhost', 514)`` is used.  The address is used to open a socket.  An
    alternative to providing a ``(host, port)`` tuple is providing an address as a
    string, for example "/dev/log". In this case, a Unix domain socket is used to
    send the message to the syslog. If *facility* is not specified,
-   :const:`LOG_USER` is used.
+   :const:`LOG_USER` is used. The type of socket opened depends on the
+   *socktype* argument, which defaults to :const:`socket.SOCK_DGRAM` and thus
+   opens a UDP socket. To open a TCP socket (for use with the newer syslog
+   daemons such as rsyslog), specify a value of :const:`socket.SOCK_STREAM`.
+
+   .. versionchanged:: 3.2
+      *socktype* was added.
 
 
    .. method:: close()

Modified: python/branches/py3k/Lib/logging/__init__.py
==============================================================================
--- python/branches/py3k/Lib/logging/__init__.py	(original)
+++ python/branches/py3k/Lib/logging/__init__.py	Sat Oct 10 22:32:36 2009
@@ -46,8 +46,8 @@
 
 __author__  = "Vinay Sajip <vinay_sajip at red-dove.com>"
 __status__  = "production"
-__version__ = "0.5.0.7"
-__date__    = "20 January 2009"
+__version__ = "0.5.0.9"
+__date__    = "09 October 2009"
 
 #---------------------------------------------------------------------------
 #   Miscellaneous module data

Modified: python/branches/py3k/Lib/logging/config.py
==============================================================================
--- python/branches/py3k/Lib/logging/config.py	(original)
+++ python/branches/py3k/Lib/logging/config.py	Sat Oct 10 22:32:36 2009
@@ -19,7 +19,7 @@
 is based on PEP 282 and comments thereto in comp.lang.python, and influenced
 by Apache's log4j system.
 
-Copyright (C) 2001-2008 Vinay Sajip. All Rights Reserved.
+Copyright (C) 2001-2009 Vinay Sajip. All Rights Reserved.
 
 To use, simply 'import logging' and log away!
 """

Modified: python/branches/py3k/Lib/logging/handlers.py
==============================================================================
--- python/branches/py3k/Lib/logging/handlers.py	(original)
+++ python/branches/py3k/Lib/logging/handlers.py	Sat Oct 10 22:32:36 2009
@@ -1,4 +1,4 @@
-# Copyright 2001-2007 by Vinay Sajip. All Rights Reserved.
+# Copyright 2001-2009 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,
@@ -41,6 +41,7 @@
 DEFAULT_HTTP_LOGGING_PORT   = 9022
 DEFAULT_SOAP_LOGGING_PORT   = 9023
 SYSLOG_UDP_PORT             = 514
+SYSLOG_TCP_PORT             = 514
 
 _MIDNIGHT = 24 * 60 * 60  # number of seconds in a day
 
@@ -155,7 +156,7 @@
     If backupCount is > 0, when rollover is done, no more than backupCount
     files are kept - the oldest ones are deleted.
     """
-    def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=0, utc=False):
+    def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False):
         BaseRotatingHandler.__init__(self, filename, 'a', encoding, delay)
         self.when = when.upper()
         self.backupCount = backupCount
@@ -690,7 +691,8 @@
         "CRITICAL" : "critical"
     }
 
-    def __init__(self, address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER):
+    def __init__(self, address=('localhost', SYSLOG_UDP_PORT),
+                 facility=LOG_USER, socktype=socket.SOCK_DGRAM):
         """
         Initialize a handler.
 
@@ -702,13 +704,16 @@
 
         self.address = address
         self.facility = facility
+        self.socktype = socktype
+
         if isinstance(address, str):
             self.unixsocket = 1
             self._connect_unixsocket(address)
         else:
             self.unixsocket = 0
-            self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-
+            self.socket = socket.socket(socket.AF_INET, socktype)
+            if socktype == socket.SOCK_STREAM:
+                self.socket.connect(address)
         self.formatter = None
 
     def _connect_unixsocket(self, address):
@@ -781,8 +786,10 @@
                 except socket.error:
                     self._connect_unixsocket(self.address)
                     self.socket.send(msg)
-            else:
+            elif self.socktype == socket.SOCK_DGRAM:
                 self.socket.sendto(msg, self.address)
+            else:
+                self.socket.sendall(msg)
         except (KeyboardInterrupt, SystemExit):
             raise
         except:

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Sat Oct 10 22:32:36 2009
@@ -87,6 +87,9 @@
 Library
 -------
 
+- Issue #7086: Added TCP support to SysLogHandler, and tidied up some
+  anachronisms in the code which were a relic of 1.5.2 compatibility.
+  
 - Issue #7082: When falling back to the MIME 'name' parameter, the
   correct place to look for it is the Content-Type header.
 

Modified: python/trunk/Doc/library/logging.rst
==============================================================================
--- python/trunk/Doc/library/logging.rst	(original)
+++ python/trunk/Doc/library/logging.rst	Sat Oct 10 22:32:36 2009
@@ -764,12 +764,12 @@
 
    Does basic configuration for the logging system by creating a
    :class:`StreamHandler` with a default :class:`Formatter` and adding it to the
-   root logger. The function does nothing if any handlers have been defined for
-   the root logger. The functions :func:`debug`, :func:`info`, :func:`warning`,
+   root logger. The functions :func:`debug`, :func:`info`, :func:`warning`,
    :func:`error` and :func:`critical` will call :func:`basicConfig` automatically
    if no handlers are defined for the root logger.
 
-   This function does nothing if the root logger already has handlers configured.
+   This function does nothing if the root logger already has handlers
+   configured for it.
 
    .. versionchanged:: 2.4
       Formerly, :func:`basicConfig` did not take any keyword arguments.
@@ -2008,16 +2008,22 @@
 supports sending logging messages to a remote or local Unix syslog.
 
 
-.. class:: SysLogHandler([address[, facility]])
+.. class:: SysLogHandler([address[, facility[, socktype]]])
 
    Returns a new instance of the :class:`SysLogHandler` class intended to
    communicate with a remote Unix machine whose address is given by *address* in
    the form of a ``(host, port)`` tuple.  If *address* is not specified,
-   ``('localhost', 514)`` is used.  The address is used to open a UDP socket.  An
+   ``('localhost', 514)`` is used.  The address is used to open a socket.  An
    alternative to providing a ``(host, port)`` tuple is providing an address as a
    string, for example "/dev/log". In this case, a Unix domain socket is used to
    send the message to the syslog. If *facility* is not specified,
-   :const:`LOG_USER` is used.
+   :const:`LOG_USER` is used. The type of socket opened depends on the
+   *socktype* argument, which defaults to :const:`socket.SOCK_DGRAM` and thus
+   opens a UDP socket. To open a TCP socket (for use with the newer syslog
+   daemons such as rsyslog), specify a value of :const:`socket.SOCK_STREAM`.
+
+   .. versionchanged:: 2.7
+      *socktype* was added.
 
 
    .. method:: close()

Modified: python/trunk/Lib/logging/__init__.py
==============================================================================
--- python/trunk/Lib/logging/__init__.py	(original)
+++ python/trunk/Lib/logging/__init__.py	Sat Oct 10 22:32:36 2009
@@ -23,6 +23,8 @@
 To use, simply 'import logging' and log away!
 """
 
+import sys, os, time, cStringIO, traceback, warnings
+
 __all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
            'FATAL', 'FileHandler', 'Filter', 'Formatter', 'Handler', 'INFO',
            'LogRecord', 'Logger', 'LoggerAdapter', 'NOTSET', 'NullHandler',
@@ -31,8 +33,6 @@
            'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass',
            'info', 'log', 'makeLogRecord', 'setLoggerClass', 'warn', 'warning']
 
-import sys, os, types, time, string, cStringIO, traceback, warnings
-
 try:
     import codecs
 except ImportError:
@@ -46,12 +46,17 @@
 
 __author__  = "Vinay Sajip <vinay_sajip at red-dove.com>"
 __status__  = "production"
-__version__ = "0.5.0.8"
-__date__    = "27 April 2009"
+__version__ = "0.5.0.9"
+__date__    = "09 October 2009"
 
 #---------------------------------------------------------------------------
 #   Miscellaneous module data
 #---------------------------------------------------------------------------
+try:
+    unicode
+    _unicode = True
+except NameError:
+    _unicode = False
 
 #
 # _srcfile is used when walking the stack to check when we've got the first
@@ -59,7 +64,7 @@
 #
 if hasattr(sys, 'frozen'): #support for py2exe
     _srcfile = "logging%s__init__%s" % (os.sep, __file__[-4:])
-elif string.lower(__file__[-4:]) in ['.pyc', '.pyo']:
+elif __file__[-4:].lower() in ['.pyc', '.pyo']:
     _srcfile = __file__[:-4] + '.py'
 else:
     _srcfile = __file__
@@ -71,7 +76,7 @@
     try:
         raise Exception
     except:
-        return sys.exc_traceback.tb_frame.f_back
+        return sys.exc_info()[2].tb_frame.f_back
 
 if hasattr(sys, '_getframe'): currentframe = lambda: sys._getframe(3)
 # done filching
@@ -255,9 +260,7 @@
         # 'Value is %d' instead of 'Value is 0'.
         # For the use case of passing a dictionary, this should not be a
         # problem.
-        if args and len(args) == 1 and (
-                                        type(args[0]) == types.DictType
-                                       ) and args[0]:
+        if args and len(args) == 1 and isinstance(args[0], dict) and args[0]:
             args = args[0]
         self.args = args
         self.levelname = getLevelName(level)
@@ -306,11 +309,11 @@
         Return the message for this LogRecord after merging any user-supplied
         arguments with the message.
         """
-        if not hasattr(types, "UnicodeType"): #if no unicode support...
+        if not _unicode: #if no unicode support...
             msg = str(self.msg)
         else:
             msg = self.msg
-            if type(msg) not in (types.UnicodeType, types.StringType):
+            if not isinstance(msg, basestring):
                 try:
                     msg = str(self.msg)
                 except UnicodeError:
@@ -447,7 +450,7 @@
         formatException() and appended to the message.
         """
         record.message = record.getMessage()
-        if string.find(self._fmt,"%(asctime)") >= 0:
+        if self._fmt.find("%(asctime)") >= 0:
             record.asctime = self.formatTime(record, self.datefmt)
         s = self._fmt % record.__dict__
         if record.exc_info:
@@ -541,7 +544,7 @@
             return 1
         elif self.name == record.name:
             return 1
-        elif string.find(record.name, self.name, 0, self.nlen) != 0:
+        elif record.name.find(self.name, 0, self.nlen) != 0:
             return 0
         return (record.name[self.nlen] == ".")
 
@@ -667,8 +670,8 @@
         This version is intended to be implemented by subclasses and so
         raises a NotImplementedError.
         """
-        raise NotImplementedError, 'emit must be implemented '\
-                                    'by Handler subclasses'
+        raise NotImplementedError('emit must be implemented '
+                                  'by Handler subclasses')
 
     def handle(self, record):
         """
@@ -781,7 +784,7 @@
             msg = self.format(record)
             stream = self.stream
             fs = "%s\n"
-            if not hasattr(types, "UnicodeType"): #if no unicode support...
+            if not _unicode: #if no unicode support...
                 stream.write(fs % msg)
             else:
                 try:
@@ -903,8 +906,8 @@
     """
     if klass != Logger:
         if not issubclass(klass, Logger):
-            raise TypeError, "logger not derived from logging.Logger: " + \
-                            klass.__name__
+            raise TypeError("logger not derived from logging.Logger: "
+                            + klass.__name__)
     global _loggerClass
     _loggerClass = klass
 
@@ -967,7 +970,7 @@
         from the specified logger to the root of the logger hierarchy.
         """
         name = alogger.name
-        i = string.rfind(name, ".")
+        i = name.rfind(".")
         rv = None
         while (i > 0) and not rv:
             substr = name[:i]
@@ -980,7 +983,7 @@
                 else:
                     assert isinstance(obj, PlaceHolder)
                     obj.append(alogger)
-            i = string.rfind(name, ".", 0, i - 1)
+            i = name.rfind(".", 0, i - 1)
         if not rv:
             rv = self.root
         alogger.parent = rv
@@ -994,7 +997,6 @@
         namelen = len(name)
         for c in ph.loggerMap.keys():
             #The if means ... if not c.parent.name.startswith(nm)
-            #if string.find(c.parent.name, nm) <> 0:
             if c.parent.name[:namelen] != name:
                 alogger.parent = c.parent
                 c.parent = alogger
@@ -1090,7 +1092,7 @@
         """
         Convenience method for logging an ERROR with exception information.
         """
-        self.error(*((msg,) + args), **{'exc_info': 1})
+        self.error(msg, exc_info=1, *args)
 
     def critical(self, msg, *args, **kwargs):
         """
@@ -1115,9 +1117,9 @@
 
         logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
         """
-        if type(level) != types.IntType:
+        if not isinstance(level, int):
             if raiseExceptions:
-                raise TypeError, "level must be an integer"
+                raise TypeError("level must be an integer")
             else:
                 return
         if self.isEnabledFor(level):
@@ -1173,7 +1175,7 @@
         else:
             fn, lno, func = "(unknown file)", 0, "(unknown function)"
         if exc_info:
-            if type(exc_info) != types.TupleType:
+            if not isinstance(exc_info, tuple):
                 exc_info = sys.exc_info()
         record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra)
         self.handle(record)
@@ -1449,7 +1451,7 @@
     """
     if len(root.handlers) == 0:
         basicConfig()
-    root.critical(*((msg,)+args), **kwargs)
+    root.critical(msg, *args, **kwargs)
 
 fatal = critical
 
@@ -1459,14 +1461,14 @@
     """
     if len(root.handlers) == 0:
         basicConfig()
-    root.error(*((msg,)+args), **kwargs)
+    root.error(msg, *args, **kwargs)
 
 def exception(msg, *args):
     """
     Log a message with severity 'ERROR' on the root logger,
     with exception information.
     """
-    error(*((msg,)+args), **{'exc_info': 1})
+    error(msg, exc_info=1, *args)
 
 def warning(msg, *args, **kwargs):
     """
@@ -1474,7 +1476,7 @@
     """
     if len(root.handlers) == 0:
         basicConfig()
-    root.warning(*((msg,)+args), **kwargs)
+    root.warning(msg, *args, **kwargs)
 
 warn = warning
 
@@ -1484,7 +1486,7 @@
     """
     if len(root.handlers) == 0:
         basicConfig()
-    root.info(*((msg,)+args), **kwargs)
+    root.info(msg, *args, **kwargs)
 
 def debug(msg, *args, **kwargs):
     """
@@ -1492,7 +1494,7 @@
     """
     if len(root.handlers) == 0:
         basicConfig()
-    root.debug(*((msg,)+args), **kwargs)
+    root.debug(msg, *args, **kwargs)
 
 def log(level, msg, *args, **kwargs):
     """
@@ -1500,7 +1502,7 @@
     """
     if len(root.handlers) == 0:
         basicConfig()
-    root.log(*((level, msg)+args), **kwargs)
+    root.log(level, msg, *args, **kwargs)
 
 def disable(level):
     """

Modified: python/trunk/Lib/logging/config.py
==============================================================================
--- python/trunk/Lib/logging/config.py	(original)
+++ python/trunk/Lib/logging/config.py	Sat Oct 10 22:32:36 2009
@@ -19,15 +19,12 @@
 is based on PEP 282 and comments thereto in comp.lang.python, and influenced
 by Apache's log4j system.
 
-Should work under Python versions >= 1.5.2, except that source line
-information is not available unless 'sys._getframe()' is.
-
-Copyright (C) 2001-2008 Vinay Sajip. All Rights Reserved.
+Copyright (C) 2001-2009 Vinay Sajip. All Rights Reserved.
 
 To use, simply 'import logging' and log away!
 """
 
-import sys, logging, logging.handlers, string, socket, struct, os, traceback, types
+import sys, logging, logging.handlers, socket, struct, os, traceback
 
 try:
     import thread
@@ -52,7 +49,7 @@
 #   _listener holds the server object doing the listening
 _listener = None
 
-def fileConfig(fname, defaults=None, disable_existing_loggers=1):
+def fileConfig(fname, defaults=None, disable_existing_loggers=True):
     """
     Read the logging configuration from a ConfigParser-format file.
 
@@ -89,7 +86,7 @@
 
 def _resolve(name):
     """Resolve a dotted name to a global object."""
-    name = string.split(name, '.')
+    name = name.split('.')
     used = name.pop(0)
     found = __import__(used)
     for n in name:
@@ -102,14 +99,14 @@
     return found
 
 def _strip_spaces(alist):
-    return map(lambda x: string.strip(x), alist)
+    return map(lambda x: x.strip(), alist)
 
 def _create_formatters(cp):
     """Create and return formatters"""
     flist = cp.get("formatters", "keys")
     if not len(flist):
         return {}
-    flist = string.split(flist, ",")
+    flist = flist.split(",")
     flist = _strip_spaces(flist)
     formatters = {}
     for form in flist:
@@ -138,7 +135,7 @@
     hlist = cp.get("handlers", "keys")
     if not len(hlist):
         return {}
-    hlist = string.split(hlist, ",")
+    hlist = hlist.split(",")
     hlist = _strip_spaces(hlist)
     handlers = {}
     fixups = [] #for inter-handler references
@@ -181,8 +178,8 @@
 
     # configure the root first
     llist = cp.get("loggers", "keys")
-    llist = string.split(llist, ",")
-    llist = map(lambda x: string.strip(x), llist)
+    llist = llist.split(",")
+    llist = list(map(lambda x: x.strip(), llist))
     llist.remove("root")
     sectname = "logger_root"
     root = logging.root
@@ -195,7 +192,7 @@
         root.removeHandler(h)
     hlist = cp.get(sectname, "handlers")
     if len(hlist):
-        hlist = string.split(hlist, ",")
+        hlist = hlist.split(",")
         hlist = _strip_spaces(hlist)
         for hand in hlist:
             log.addHandler(handlers[hand])
@@ -209,7 +206,7 @@
     #what's left in existing is the set of loggers
     #which were in the previous configuration but
     #which are not in the new configuration.
-    existing = root.manager.loggerDict.keys()
+    existing = list(root.manager.loggerDict.keys())
     #The list needs to be sorted so that we can
     #avoid disabling child loggers of explicitly
     #named loggers. With a sorted list it is easier
@@ -247,7 +244,7 @@
         logger.disabled = 0
         hlist = cp.get(sectname, "handlers")
         if len(hlist):
-            hlist = string.split(hlist, ",")
+            hlist = hlist.split(",")
             hlist = _strip_spaces(hlist)
             for hand in hlist:
                 logger.addHandler(handlers[hand])
@@ -278,7 +275,7 @@
     stopListening().
     """
     if not thread:
-        raise NotImplementedError, "listen() needs threading to work"
+        raise NotImplementedError("listen() needs threading to work")
 
     class ConfigStreamHandler(StreamRequestHandler):
         """
@@ -321,7 +318,7 @@
                         traceback.print_exc()
                     os.remove(file)
             except socket.error, e:
-                if type(e.args) != types.TupleType:
+                if not isinstance(e.args, tuple):
                     raise
                 else:
                     errcode = e.args[0]

Modified: python/trunk/Lib/logging/handlers.py
==============================================================================
--- python/trunk/Lib/logging/handlers.py	(original)
+++ python/trunk/Lib/logging/handlers.py	Sat Oct 10 22:32:36 2009
@@ -24,7 +24,7 @@
 To use, simply 'import logging.handlers' and log away!
 """
 
-import logging, socket, types, os, string, cPickle, struct, time, re
+import logging, socket, os, cPickle, struct, time, re
 from stat import ST_DEV, ST_INO
 
 try:
@@ -41,6 +41,7 @@
 DEFAULT_HTTP_LOGGING_PORT   = 9022
 DEFAULT_SOAP_LOGGING_PORT   = 9023
 SYSLOG_UDP_PORT             = 514
+SYSLOG_TCP_PORT             = 514
 
 _MIDNIGHT = 24 * 60 * 60  # number of seconds in a day
 
@@ -155,9 +156,9 @@
     If backupCount is > 0, when rollover is done, no more than backupCount
     files are kept - the oldest ones are deleted.
     """
-    def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=0, utc=0):
+    def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False):
         BaseRotatingHandler.__init__(self, filename, 'a', encoding, delay)
-        self.when = string.upper(when)
+        self.when = when.upper()
         self.backupCount = backupCount
         self.utc = utc
         # Calculate the real rollover interval, which is just the number of
@@ -204,8 +205,6 @@
         self.interval = self.interval * interval # multiply by units requested
         self.rolloverAt = self.computeRollover(int(time.time()))
 
-        #print "Will rollover at %d, %d seconds from now" % (self.rolloverAt, self.rolloverAt - currentTime)
-
     def computeRollover(self, currentTime):
         """
         Work out the rollover time based on the specified time.
@@ -692,7 +691,8 @@
         "CRITICAL" : "critical"
     }
 
-    def __init__(self, address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER):
+    def __init__(self, address=('localhost', SYSLOG_UDP_PORT),
+                 facility=LOG_USER, socktype=socket.SOCK_DGRAM):
         """
         Initialize a handler.
 
@@ -704,13 +704,16 @@
 
         self.address = address
         self.facility = facility
-        if type(address) == types.StringType:
+        self.socktype = socktype
+
+        if isinstance(address, basestring):
             self.unixsocket = 1
             self._connect_unixsocket(address)
         else:
             self.unixsocket = 0
-            self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-
+            self.socket = socket.socket(socket.AF_INET, socktype)
+            if socktype == socket.SOCK_STREAM:
+                self.socket.connect(address)
         self.formatter = None
 
     def _connect_unixsocket(self, address):
@@ -736,9 +739,9 @@
         priority_names mapping dictionaries are used to convert them to
         integers.
         """
-        if type(facility) == types.StringType:
+        if isinstance(facility, basestring):
             facility = self.facility_names[facility]
-        if type(priority) == types.StringType:
+        if isinstance(priority, basestring):
             priority = self.priority_names[priority]
         return (facility << 3) | priority
 
@@ -783,8 +786,10 @@
                 except socket.error:
                     self._connect_unixsocket(self.address)
                     self.socket.send(msg)
-            else:
+            elif self.socktype == socket.SOCK_DGRAM:
                 self.socket.sendto(msg, self.address)
+            else:
+                self.socket.sendall(msg)
         except (KeyboardInterrupt, SystemExit):
             raise
         except:
@@ -805,16 +810,16 @@
         for the credentials argument.
         """
         logging.Handler.__init__(self)
-        if type(mailhost) == types.TupleType:
+        if isinstance(mailhost, tuple):
             self.mailhost, self.mailport = mailhost
         else:
             self.mailhost, self.mailport = mailhost, None
-        if type(credentials) == types.TupleType:
+        if isinstance(credentials, tuple):
             self.username, self.password = credentials
         else:
             self.username = None
         self.fromaddr = fromaddr
-        if type(toaddrs) == types.StringType:
+        if isinstance(toaddrs, basestring):
             toaddrs = [toaddrs]
         self.toaddrs = toaddrs
         self.subject = subject
@@ -865,7 +870,7 @@
             msg = self.format(record)
             msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\nDate: %s\r\n\r\n%s" % (
                             self.fromaddr,
-                            string.join(self.toaddrs, ","),
+                            ",".join(self.toaddrs),
                             self.getSubject(record),
                             formatdate(), msg)
             if self.username:
@@ -909,8 +914,8 @@
                 logging.CRITICAL: win32evtlog.EVENTLOG_ERROR_TYPE,
          }
         except ImportError:
-            print "The Python Win32 extensions for NT (service, event "\
-                        "logging) appear not to be available."
+            print("The Python Win32 extensions for NT (service, event "\
+                        "logging) appear not to be available.")
             self._welu = None
 
     def getMessageID(self, record):
@@ -988,9 +993,9 @@
         ("GET" or "POST")
         """
         logging.Handler.__init__(self)
-        method = string.upper(method)
+        method = method.upper()
         if method not in ["GET", "POST"]:
-            raise ValueError, "method must be GET or POST"
+            raise ValueError("method must be GET or POST")
         self.host = host
         self.url = url
         self.method = method
@@ -1016,7 +1021,7 @@
             url = self.url
             data = urllib.urlencode(self.mapLogRecord(record))
             if self.method == "GET":
-                if (string.find(url, '?') >= 0):
+                if (url.find('?') >= 0):
                     sep = '&'
                 else:
                     sep = '?'
@@ -1024,7 +1029,7 @@
             h.putrequest(self.method, url)
             # support multiple hosts on one IP address...
             # need to strip optional :port from host, if present
-            i = string.find(host, ":")
+            i = host.find(":")
             if i >= 0:
                 host = host[:i]
             h.putheader("Host", host)

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Sat Oct 10 22:32:36 2009
@@ -398,6 +398,9 @@
 Library
 -------
 
+- Issue #7086: Added TCP support to SysLogHandler, and tidied up some
+  anachronisms in the code which were a relic of 1.5.2 compatibility.
+  
 - Issue #7082: When falling back to the MIME 'name' parameter, the
   correct place to look for it is the Content-Type header.
 


More information about the Python-checkins mailing list