Commit cfa714b2 authored by Benjamin Peterson's avatar Benjamin Peterson

Merged revisions 76498,76507-76509 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r76498 | vinay.sajip | 2009-11-24 09:53:25 -0600 (Tue, 24 Nov 2009) | 1 line

  Made logging classes new-style and added name property to handlers.
........
  r76507 | vinay.sajip | 2009-11-25 03:03:30 -0600 (Wed, 25 Nov 2009) | 1 line

  Issue #6615: logging: Used weak references in internal handler list. Thanks to flox (Florent Xicluna) for the patch.
........
  r76508 | vinay.sajip | 2009-11-25 03:22:47 -0600 (Wed, 25 Nov 2009) | 1 line

  logging: made _handlers a WeakValueDictionary.
........
  r76509 | vinay.sajip | 2009-11-25 08:12:03 -0600 (Wed, 25 Nov 2009) | 1 line

  logging: Issue 6615: Changed handler prepend to append.
........
parent 04b0f12d
...@@ -23,7 +23,7 @@ Copyright (C) 2001-2009 Vinay Sajip. All Rights Reserved. ...@@ -23,7 +23,7 @@ Copyright (C) 2001-2009 Vinay Sajip. All Rights Reserved.
To use, simply 'import logging' and log away! To use, simply 'import logging' and log away!
""" """
import sys, os, time, io, traceback, warnings import sys, os, time, io, traceback, warnings, weakref
__all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR', __all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
'FATAL', 'FileHandler', 'Filter', 'Formatter', 'Handler', 'INFO', 'FATAL', 'FileHandler', 'Filter', 'Formatter', 'Handler', 'INFO',
...@@ -46,8 +46,8 @@ except ImportError: ...@@ -46,8 +46,8 @@ except ImportError:
__author__ = "Vinay Sajip <vinay_sajip@red-dove.com>" __author__ = "Vinay Sajip <vinay_sajip@red-dove.com>"
__status__ = "production" __status__ = "production"
__version__ = "0.5.0.9" __version__ = "0.5.1.1"
__date__ = "09 October 2009" __date__ = "25 November 2009"
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Miscellaneous module data # Miscellaneous module data
...@@ -193,9 +193,9 @@ def _checkLevel(level): ...@@ -193,9 +193,9 @@ def _checkLevel(level):
# #
#_lock is used to serialize access to shared data structures in this module. #_lock is used to serialize access to shared data structures in this module.
#This needs to be an RLock because fileConfig() creates Handlers and so #This needs to be an RLock because fileConfig() creates and configures
#might arbitrary user threads. Since Handler.__init__() updates the shared #Handlers, and so might arbitrary user threads. Since Handler code updates the
#dictionary _handlers, it needs to acquire the lock. But if configuring, #shared dictionary _handlers, it needs to acquire the lock. But if configuring,
#the lock would already have been acquired - so we need an RLock. #the lock would already have been acquired - so we need an RLock.
#The same argument applies to Loggers and Manager.loggerDict. #The same argument applies to Loggers and Manager.loggerDict.
# #
...@@ -224,7 +224,7 @@ def _releaseLock(): ...@@ -224,7 +224,7 @@ def _releaseLock():
# The logging record # The logging record
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
class LogRecord: class LogRecord(object):
""" """
A LogRecord instance represents an event being logged. A LogRecord instance represents an event being logged.
...@@ -332,7 +332,7 @@ def makeLogRecord(dict): ...@@ -332,7 +332,7 @@ def makeLogRecord(dict):
# Formatter classes and functions # Formatter classes and functions
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
class Formatter: class Formatter(object):
""" """
Formatter instances are used to convert a LogRecord to text. Formatter instances are used to convert a LogRecord to text.
...@@ -464,7 +464,7 @@ class Formatter: ...@@ -464,7 +464,7 @@ class Formatter:
# #
_defaultFormatter = Formatter() _defaultFormatter = Formatter()
class BufferingFormatter: class BufferingFormatter(object):
""" """
A formatter suitable for formatting a number of records. A formatter suitable for formatting a number of records.
""" """
...@@ -506,7 +506,7 @@ class BufferingFormatter: ...@@ -506,7 +506,7 @@ class BufferingFormatter:
# Filter classes and functions # Filter classes and functions
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
class Filter: class Filter(object):
""" """
Filter instances are used to perform arbitrary filtering of LogRecords. Filter instances are used to perform arbitrary filtering of LogRecords.
...@@ -543,7 +543,7 @@ class Filter: ...@@ -543,7 +543,7 @@ class Filter:
return 0 return 0
return (record.name[self.nlen] == ".") return (record.name[self.nlen] == ".")
class Filterer: class Filterer(object):
""" """
A base class for loggers and handlers which allows them to share A base class for loggers and handlers which allows them to share
common code. common code.
...@@ -587,9 +587,30 @@ class Filterer: ...@@ -587,9 +587,30 @@ class Filterer:
# Handler classes and functions # Handler classes and functions
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
_handlers = {} #repository of handlers (for flushing when shutdown called) _handlers = weakref.WeakValueDictionary() #map of handler names to handlers
_handlerList = [] # added to allow handlers to be removed in reverse of order initialized _handlerList = [] # added to allow handlers to be removed in reverse of order initialized
def _removeHandlerRef(wr):
"""
Remove a handler reference from the internal cleanup list.
"""
_acquireLock()
try:
if wr in _handlerList:
_handlerList.remove(wr)
finally:
_releaseLock()
def _addHandlerRef(handler):
"""
Add a handler to the internal cleanup list using a weak reference.
"""
_acquireLock()
try:
_handlerList.append(weakref.ref(handler, _removeHandlerRef))
finally:
_releaseLock()
class Handler(Filterer): class Handler(Filterer):
""" """
Handler instances dispatch logging events to specific destinations. Handler instances dispatch logging events to specific destinations.
...@@ -605,16 +626,28 @@ class Handler(Filterer): ...@@ -605,16 +626,28 @@ class Handler(Filterer):
and the filter list to empty. and the filter list to empty.
""" """
Filterer.__init__(self) Filterer.__init__(self)
self._name = None
self.level = _checkLevel(level) self.level = _checkLevel(level)
self.formatter = None self.formatter = None
#get the module data lock, as we're updating a shared structure. # Add the handler to the global _handlerList (for cleanup on shutdown)
_addHandlerRef(self)
self.createLock()
def get_name(self):
return self._name
def set_name(self, name):
_acquireLock() _acquireLock()
try: #unlikely to raise an exception, but you never know... try:
_handlers[self] = 1 if self._name in _handlers:
_handlerList.insert(0, self) del _handlers[self._name]
self._name = name
if name:
_handlers[name] = self
finally: finally:
_releaseLock() _releaseLock()
self.createLock()
name = property(get_name, set_name)
def createLock(self): def createLock(self):
""" """
...@@ -705,16 +738,16 @@ class Handler(Filterer): ...@@ -705,16 +738,16 @@ class Handler(Filterer):
""" """
Tidy up any resources used by the handler. Tidy up any resources used by the handler.
This version does removes the handler from an internal list This version removes the handler from an internal map of handlers,
of handlers which is closed when shutdown() is called. Subclasses _handlers, which is used for handler lookup by name. Subclasses
should ensure that this gets called from overridden close() should ensure that this gets called from overridden close()
methods. methods.
""" """
#get the module data lock, as we're updating a shared structure. #get the module data lock, as we're updating a shared structure.
_acquireLock() _acquireLock()
try: #unlikely to raise an exception, but you never know... try: #unlikely to raise an exception, but you never know...
del _handlers[self] if self._name and self._name in _handlers:
_handlerList.remove(self) del _handlers[self._name]
finally: finally:
_releaseLock() _releaseLock()
...@@ -866,7 +899,7 @@ class FileHandler(StreamHandler): ...@@ -866,7 +899,7 @@ class FileHandler(StreamHandler):
# Manager classes and functions # Manager classes and functions
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
class PlaceHolder: class PlaceHolder(object):
""" """
PlaceHolder instances are used in the Manager logger hierarchy to take PlaceHolder instances are used in the Manager logger hierarchy to take
the place of nodes for which no loggers have been defined. This class is the place of nodes for which no loggers have been defined. This class is
...@@ -913,7 +946,7 @@ def getLoggerClass(): ...@@ -913,7 +946,7 @@ def getLoggerClass():
return _loggerClass return _loggerClass
class Manager: class Manager(object):
""" """
There is [under normal circumstances] just one Manager instance, which There is [under normal circumstances] just one Manager instance, which
holds the hierarchy of loggers. holds the hierarchy of loggers.
...@@ -1266,7 +1299,7 @@ class RootLogger(Logger): ...@@ -1266,7 +1299,7 @@ class RootLogger(Logger):
_loggerClass = Logger _loggerClass = Logger
class LoggerAdapter: class LoggerAdapter(object):
""" """
An adapter for loggers which makes it easier to specify contextual An adapter for loggers which makes it easier to specify contextual
information in logging output. information in logging output.
...@@ -1512,10 +1545,11 @@ def shutdown(handlerList=_handlerList): ...@@ -1512,10 +1545,11 @@ def shutdown(handlerList=_handlerList):
Should be called at application exit. Should be called at application exit.
""" """
for h in handlerList[:]: for wr in reversed(handlerList[:]):
#errors might occur, for example, if files are locked #errors might occur, for example, if files are locked
#we just ignore them if raiseExceptions is not set #we just ignore them if raiseExceptions is not set
try: try:
h = wr()
h.flush() h.flush()
h.close() h.close()
except: except:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment