[Python-checkins] r86967 - in python/branches/py3k: Doc/library/logging.rst Lib/logging/__init__.py Lib/test/test_logging.py Misc/NEWS

vinay.sajip python-checkins at python.org
Fri Dec 3 12:50:38 CET 2010


Author: vinay.sajip
Date: Fri Dec  3 12:50:38 2010
New Revision: 86967

Log:
logging: Added getLogRecordFactory/setLogRecordFactory with docs and tests.

Modified:
   python/branches/py3k/Doc/library/logging.rst
   python/branches/py3k/Lib/logging/__init__.py
   python/branches/py3k/Lib/test/test_logging.py
   python/branches/py3k/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	Fri Dec  3 12:50:38 2010
@@ -750,6 +750,19 @@
           # ... override behaviour here
 
 
+.. function:: getLogRecordFactory()
+
+   Return a callable which is used to create a :class:`LogRecord`.
+
+   .. versionadded:: 3.2
+
+      This function has been provided, along with :func:`setLogRecordFactory`,
+      to allow developers more control over how the :class:`LogRecord`
+      representing a logging event is constructed.
+
+   See :func:`setLogRecordFactory` for more information about the how the
+   factory is called.
+
 .. function:: debug(msg, *args, **kwargs)
 
    Logs a message with level :const:`DEBUG` on the root logger. The *msg* is the
@@ -973,6 +986,34 @@
    function is typically called before any loggers are instantiated by applications
    which need to use custom logger behavior.
 
+.. function:: setLogRecordFactory(factory)
+
+   Set a callable which is used to create a :class:`LogRecord`.
+
+   :param factory: The factory callable to be used to instantiate a log record.
+
+   .. versionadded:: 3.2
+
+   This function has been provided, along with :func:`getLogRecordFactory`, to
+   allow developers more control over how the :class:`LogRecord` representing
+   a logging event is constructed.
+
+   The factory has the following signature.
+
+   factory(name, level, fn, lno, msg, args, exc_info, func=None, sinfo=None, \*\*kwargs)
+
+      :name: The logger name.
+      :level: The logging level (numeric).
+      :fn: The full pathname of the file where the logging call was made.
+      :lno: The line number in the file where the logging call was made.
+      :msg: The logging message.
+      :args: The arguments for the logging message.
+      :exc_info: An exception tuple, or None.
+      :func: The name of the function or method which invoked the logging
+             call.
+      :sinfo: A stack traceback such as is provided by
+              :func:`traceback.print_stack`, showing the call hierarchy.
+      :kwargs: Additional keyword arguments.
 
 .. seealso::
 
@@ -3244,6 +3285,29 @@
       messages, whose ``__str__`` method can return the actual format string to
       be used.
 
+   .. versionchanged:: 3.2
+      The creation of a ``LogRecord`` has been made more configurable by
+      providing a factory which is used to create the record. The factory can be
+      set using :func:`getLogRecordFactory` and :func:`setLogRecordFactory`
+      (see this for the factory's signature).
+
+      This functionality can be used to inject your own values into a
+      LogRecord at creation time. You can use the following pattern::
+
+          old_factory = logging.getLogRecordFactory()
+
+          def record_factory(*args, **kwargs):
+            record = old_factory(*args, **kwargs)
+            record.custom_attribute = 0xdecafbad
+            return record
+
+          logging.setLogRecordFactory(record_factory)
+
+      With this pattern, multiple factories could be chained, and as long
+      as they don't overwrite each other's attributes or unintentionally
+      overwrite the standard attributes listed above, there should be no
+      surprises.
+
 .. _logger-adapter:
 
 LoggerAdapter Objects

Modified: python/branches/py3k/Lib/logging/__init__.py
==============================================================================
--- python/branches/py3k/Lib/logging/__init__.py	(original)
+++ python/branches/py3k/Lib/logging/__init__.py	Fri Dec  3 12:50:38 2010
@@ -33,7 +33,7 @@
            'captureWarnings', 'critical', 'debug', 'disable', 'error',
            'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass',
            'info', 'log', 'makeLogRecord', 'setLoggerClass', 'warn', 'warning',
-           'getLogRecordClass', 'setLogRecordClass']
+           'getLogRecordFactory', 'setLogRecordFactory']
 
 try:
     import codecs
@@ -238,7 +238,7 @@
     information to be logged.
     """
     def __init__(self, name, level, pathname, lineno,
-                 msg, args, exc_info, func=None, sinfo=None):
+                 msg, args, exc_info, func=None, sinfo=None, **kwargs):
         """
         Initialize a logging record with interesting information.
         """
@@ -322,21 +322,24 @@
 #
 #   Determine which class to use when instantiating log records.
 #
-_logRecordClass = LogRecord
+_logRecordFactory = LogRecord
 
-def setLogRecordClass(cls):
+def setLogRecordFactory(factory):
     """
     Set the class to be used when instantiating a log record.
+
+    :param factory: A callable which will be called to instantiate
+    a log record.
     """
-    global _logRecordClass
-    _logRecordClass = cls
+    global _logRecordFactory
+    _logRecordFactory = factory
 
-def getLogRecordClass():
+def getLogRecordFactory():
     """
     Return the class to be used when instantiating a log record.
     """
 
-    return _logRecordClass
+    return _logRecordFactory
 
 def makeLogRecord(dict):
     """
@@ -345,7 +348,7 @@
     a socket connection (which is sent as a dictionary) into a LogRecord
     instance.
     """
-    rv = _logRecordClass(None, None, "", 0, "", (), None, None)
+    rv = _logRecordFactory(None, None, "", 0, "", (), None, None)
     rv.__dict__.update(dict)
     return rv
 
@@ -1056,7 +1059,7 @@
         self.emittedNoHandlerWarning = 0
         self.loggerDict = {}
         self.loggerClass = None
-        self.logRecordClass = None
+        self.logRecordFactory = None
 
     def getLogger(self, name):
         """
@@ -1100,12 +1103,12 @@
                                 + klass.__name__)
         self.loggerClass = klass
 
-    def setLogRecordClass(self, cls):
+    def setLogRecordFactory(self, factory):
         """
         Set the class to be used when instantiating a log record with this
         Manager.
         """
-        self.logRecordClass = cls
+        self.logRecordFactory = factory
 
     def _fixupParents(self, alogger):
         """
@@ -1305,7 +1308,7 @@
         A factory method which can be overridden in subclasses to create
         specialized LogRecords.
         """
-        rv = _logRecordClass(name, level, fn, lno, msg, args, exc_info, func,
+        rv = _logRecordFactory(name, level, fn, lno, msg, args, exc_info, func,
                              sinfo)
         if extra is not None:
             for key in extra:

Modified: python/branches/py3k/Lib/test/test_logging.py
==============================================================================
--- python/branches/py3k/Lib/test/test_logging.py	(original)
+++ python/branches/py3k/Lib/test/test_logging.py	Fri Dec  3 12:50:38 2010
@@ -1799,7 +1799,7 @@
 class DerivedLogRecord(logging.LogRecord):
     pass
 
-class LogRecordClassTest(BaseTest):
+class LogRecordFactoryTest(BaseTest):
 
     def setUp(self):
         class CheckingFilter(logging.Filter):
@@ -1817,17 +1817,17 @@
         BaseTest.setUp(self)
         self.filter = CheckingFilter(DerivedLogRecord)
         self.root_logger.addFilter(self.filter)
-        self.orig_cls = logging.getLogRecordClass()
+        self.orig_factory = logging.getLogRecordFactory()
 
     def tearDown(self):
         self.root_logger.removeFilter(self.filter)
         BaseTest.tearDown(self)
-        logging.setLogRecordClass(self.orig_cls)
+        logging.setLogRecordFactory(self.orig_factory)
 
     def test_logrecord_class(self):
         self.assertRaises(TypeError, self.root_logger.warning,
                           self.next_message())
-        logging.setLogRecordClass(DerivedLogRecord)
+        logging.setLogRecordFactory(DerivedLogRecord)
         self.root_logger.error(self.next_message())
         self.assert_log_lines([
            ('root', 'ERROR', '2'),
@@ -2015,7 +2015,7 @@
                  ConfigFileTest, SocketHandlerTest, MemoryTest,
                  EncodingTest, WarningsTest, ConfigDictTest, ManagerTest,
                  FormatterTest,
-                 LogRecordClassTest, ChildLoggerTest, QueueHandlerTest,
+                 LogRecordFactoryTest, ChildLoggerTest, QueueHandlerTest,
                  RotatingFileHandlerTest,
                  #TimedRotatingFileHandlerTest
                 )

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Fri Dec  3 12:50:38 2010
@@ -33,6 +33,8 @@
 Library
 -------
 
+- logging: Added getLogRecordFactory/setLogRecordFactory with docs and tests.
+
 - Issue #10549: Fix pydoc traceback when text-documenting certain classes.
 
 - Issue #2001: New HTML server with enhanced Web page features.  Patch by Ron


More information about the Python-checkins mailing list