[Python-checkins] r76514 - in python/branches/py3k: Lib/logging/__init__.py

benjamin.peterson python-checkins at python.org
Wed Nov 25 18:19:56 CET 2009


Author: benjamin.peterson
Date: Wed Nov 25 18:19:56 2009
New Revision: 76514

Log:
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.
........


Modified:
   python/branches/py3k/   (props changed)
   python/branches/py3k/Lib/logging/__init__.py

Modified: python/branches/py3k/Lib/logging/__init__.py
==============================================================================
--- python/branches/py3k/Lib/logging/__init__.py	(original)
+++ python/branches/py3k/Lib/logging/__init__.py	Wed Nov 25 18:19:56 2009
@@ -23,7 +23,7 @@
 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',
            'FATAL', 'FileHandler', 'Filter', 'Formatter', 'Handler', 'INFO',
@@ -46,8 +46,8 @@
 
 __author__  = "Vinay Sajip <vinay_sajip at red-dove.com>"
 __status__  = "production"
-__version__ = "0.5.0.9"
-__date__    = "09 October 2009"
+__version__ = "0.5.1.1"
+__date__    = "25 November 2009"
 
 #---------------------------------------------------------------------------
 #   Miscellaneous module data
@@ -193,9 +193,9 @@
 
 #
 #_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
-#might arbitrary user threads. Since Handler.__init__() updates the shared
-#dictionary _handlers, it needs to acquire the lock. But if configuring,
+#This needs to be an RLock because fileConfig() creates and configures
+#Handlers, and so might arbitrary user threads. Since Handler code updates the
+#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 same argument applies to Loggers and Manager.loggerDict.
 #
@@ -224,7 +224,7 @@
 #   The logging record
 #---------------------------------------------------------------------------
 
-class LogRecord:
+class LogRecord(object):
     """
     A LogRecord instance represents an event being logged.
 
@@ -332,7 +332,7 @@
 #   Formatter classes and functions
 #---------------------------------------------------------------------------
 
-class Formatter:
+class Formatter(object):
     """
     Formatter instances are used to convert a LogRecord to text.
 
@@ -464,7 +464,7 @@
 #
 _defaultFormatter = Formatter()
 
-class BufferingFormatter:
+class BufferingFormatter(object):
     """
     A formatter suitable for formatting a number of records.
     """
@@ -506,7 +506,7 @@
 #   Filter classes and functions
 #---------------------------------------------------------------------------
 
-class Filter:
+class Filter(object):
     """
     Filter instances are used to perform arbitrary filtering of LogRecords.
 
@@ -543,7 +543,7 @@
             return 0
         return (record.name[self.nlen] == ".")
 
-class Filterer:
+class Filterer(object):
     """
     A base class for loggers and handlers which allows them to share
     common code.
@@ -587,9 +587,30 @@
 #   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
 
+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):
     """
     Handler instances dispatch logging events to specific destinations.
@@ -605,16 +626,28 @@
         and the filter list to empty.
         """
         Filterer.__init__(self)
+        self._name = None
         self.level = _checkLevel(level)
         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()
-        try:    #unlikely to raise an exception, but you never know...
-            _handlers[self] = 1
-            _handlerList.insert(0, self)
+        try:
+            if self._name in _handlers:
+                del _handlers[self._name]
+            self._name = name
+            if name:
+                _handlers[name] = self
         finally:
             _releaseLock()
-        self.createLock()
+
+    name = property(get_name, set_name)
 
     def createLock(self):
         """
@@ -705,16 +738,16 @@
         """
         Tidy up any resources used by the handler.
 
-        This version does removes the handler from an internal list
-        of handlers which is closed when shutdown() is called. Subclasses
+        This version removes the handler from an internal map of handlers,
+        _handlers, which is used for handler lookup by name. Subclasses
         should ensure that this gets called from overridden close()
         methods.
         """
         #get the module data lock, as we're updating a shared structure.
         _acquireLock()
         try:    #unlikely to raise an exception, but you never know...
-            del _handlers[self]
-            _handlerList.remove(self)
+            if self._name and self._name in _handlers:
+                del _handlers[self._name]
         finally:
             _releaseLock()
 
@@ -866,7 +899,7 @@
 #   Manager classes and functions
 #---------------------------------------------------------------------------
 
-class PlaceHolder:
+class PlaceHolder(object):
     """
     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
@@ -913,7 +946,7 @@
 
     return _loggerClass
 
-class Manager:
+class Manager(object):
     """
     There is [under normal circumstances] just one Manager instance, which
     holds the hierarchy of loggers.
@@ -1266,7 +1299,7 @@
 
 _loggerClass = Logger
 
-class LoggerAdapter:
+class LoggerAdapter(object):
     """
     An adapter for loggers which makes it easier to specify contextual
     information in logging output.
@@ -1512,10 +1545,11 @@
 
     Should be called at application exit.
     """
-    for h in handlerList[:]:
+    for wr in reversed(handlerList[:]):
         #errors might occur, for example, if files are locked
         #we just ignore them if raiseExceptions is not set
         try:
+            h = wr()
             h.flush()
             h.close()
         except:


More information about the Python-checkins mailing list