Issue #7086: Added TCP support to SysLogHandler and tidied up some anachronisms in the code.
This commit is contained in:
parent
6e3dbbdf39
commit
1c77b7f84c
|
@ -764,12 +764,12 @@ functions.
|
|||
|
||||
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 @@ The :class:`SysLogHandler` class, located in the :mod:`logging.handlers` module,
|
|||
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()
|
||||
|
|
|
@ -23,6 +23,8 @@ Copyright (C) 2001-2009 Vinay Sajip. All Rights Reserved.
|
|||
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 @@ __all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
|
|||
'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 @@ except ImportError:
|
|||
|
||||
__author__ = "Vinay Sajip <vinay_sajip@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 @@ __date__ = "27 April 2009"
|
|||
#
|
||||
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 @@ def currentframe():
|
|||
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 @@ class LogRecord:
|
|||
# '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 @@ class LogRecord:
|
|||
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 @@ class Formatter:
|
|||
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 @@ class Filter:
|
|||
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 @@ class Handler(Filterer):
|
|||
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 @@ class StreamHandler(Handler):
|
|||
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 @@ def setLoggerClass(klass):
|
|||
"""
|
||||
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 @@ class Manager:
|
|||
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 @@ class Manager:
|
|||
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 @@ class Manager:
|
|||
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 @@ class Logger(Filterer):
|
|||
"""
|
||||
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 @@ class Logger(Filterer):
|
|||
|
||||
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 @@ class Logger(Filterer):
|
|||
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 @@ def critical(msg, *args, **kwargs):
|
|||
"""
|
||||
if len(root.handlers) == 0:
|
||||
basicConfig()
|
||||
root.critical(*((msg,)+args), **kwargs)
|
||||
root.critical(msg, *args, **kwargs)
|
||||
|
||||
fatal = critical
|
||||
|
||||
|
@ -1459,14 +1461,14 @@ def error(msg, *args, **kwargs):
|
|||
"""
|
||||
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 @@ def warning(msg, *args, **kwargs):
|
|||
"""
|
||||
if len(root.handlers) == 0:
|
||||
basicConfig()
|
||||
root.warning(*((msg,)+args), **kwargs)
|
||||
root.warning(msg, *args, **kwargs)
|
||||
|
||||
warn = warning
|
||||
|
||||
|
@ -1484,7 +1486,7 @@ def info(msg, *args, **kwargs):
|
|||
"""
|
||||
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 @@ def debug(msg, *args, **kwargs):
|
|||
"""
|
||||
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 @@ def log(level, msg, *args, **kwargs):
|
|||
"""
|
||||
if len(root.handlers) == 0:
|
||||
basicConfig()
|
||||
root.log(*((level, msg)+args), **kwargs)
|
||||
root.log(level, msg, *args, **kwargs)
|
||||
|
||||
def disable(level):
|
||||
"""
|
||||
|
|
|
@ -19,15 +19,12 @@ Configuration functions for the logging package for Python. The core package
|
|||
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 @@ else:
|
|||
# _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 fileConfig(fname, defaults=None, disable_existing_loggers=1):
|
|||
|
||||
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 @@ def _resolve(name):
|
|||
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 @@ def _install_handlers(cp, formatters):
|
|||
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 @@ def _install_loggers(cp, handlers, disable_existing_loggers):
|
|||
|
||||
# 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 @@ def _install_loggers(cp, handlers, disable_existing_loggers):
|
|||
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 @@ def _install_loggers(cp, handlers, disable_existing_loggers):
|
|||
#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 @@ def _install_loggers(cp, handlers, disable_existing_loggers):
|
|||
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 @@ def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
|
|||
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 @@ def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
|
|||
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]
|
||||
|
|
|
@ -24,7 +24,7 @@ Copyright (C) 2001-2009 Vinay Sajip. All Rights Reserved.
|
|||
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_UDP_LOGGING_PORT = 9021
|
|||
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 @@ class TimedRotatingFileHandler(BaseRotatingHandler):
|
|||
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 @@ class TimedRotatingFileHandler(BaseRotatingHandler):
|
|||
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 @@ class SysLogHandler(logging.Handler):
|
|||
"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 @@ class SysLogHandler(logging.Handler):
|
|||
|
||||
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 @@ class SysLogHandler(logging.Handler):
|
|||
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 @@ class SysLogHandler(logging.Handler):
|
|||
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 @@ class SMTPHandler(logging.Handler):
|
|||
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 @@ class SMTPHandler(logging.Handler):
|
|||
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 @@ class NTEventLogHandler(logging.Handler):
|
|||
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 @@ class HTTPHandler(logging.Handler):
|
|||
("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 @@ class HTTPHandler(logging.Handler):
|
|||
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 @@ class HTTPHandler(logging.Handler):
|
|||
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)
|
||||
|
|
|
@ -398,6 +398,9 @@ Core and Builtins
|
|||
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.
|
||||
|
||||
|
|
Loading…
Reference in New Issue