]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Closes #20537: logging methods now accept an exception instance as well as a Boolean...
authorVinay Sajip <vinay_sajip@yahoo.co.uk>
Sun, 14 Sep 2014 20:29:11 +0000 (21:29 +0100)
committerVinay Sajip <vinay_sajip@yahoo.co.uk>
Sun, 14 Sep 2014 20:29:11 +0000 (21:29 +0100)
Doc/library/logging.rst
Lib/logging/__init__.py
Lib/test/test_logging.py
Misc/NEWS

index 9983711644366363368d5766b96832e1958fa03d..d0e2c276d022ff0c625e37c5d06f59f1ee13f2f0 100644 (file)
@@ -155,11 +155,13 @@ is the module's name in the Python package namespace.
    *msg* using the string formatting operator. (Note that this means that you can
    use keywords in the format string, together with a single dictionary argument.)
 
-   There are three keyword arguments in *kwargs* which are inspected: *exc_info*
-   which, if it does not evaluate as false, causes exception information to be
+   There are three keyword arguments in *kwargs* which are inspected:
+   *exc_info*, *stack_info*, and *extra*.
+
+   If *exc_info* does not evaluate as false, it causes exception information to be
    added to the logging message. If an exception tuple (in the format returned by
-   :func:`sys.exc_info`) is provided, it is used; otherwise, :func:`sys.exc_info`
-   is called to get the exception information.
+   :func:`sys.exc_info`) or an exception instance is provided, it is used;
+   otherwise, :func:`sys.exc_info` is called to get the exception information.
 
    The second optional keyword argument is *stack_info*, which defaults to
    ``False``. If true, stack information is added to the logging
@@ -216,6 +218,9 @@ is the module's name in the Python package namespace.
    .. versionadded:: 3.2
       The *stack_info* parameter was added.
 
+   .. versionchanged:: 3.5
+      The *exc_info* parameter can now accept exception instances.
+
 
 .. method:: Logger.info(msg, *args, **kwargs)
 
index 7fb3a352e597a1dff0b45bb7da7e66e8f21c4d51..7628d84b438ba1243eddc7493e4951be0abb37fb 100644 (file)
@@ -1302,12 +1302,11 @@ class Logger(Filterer):
         if self.isEnabledFor(ERROR):
             self._log(ERROR, msg, args, **kwargs)
 
-    def exception(self, msg, *args, **kwargs):
+    def exception(self, msg, *args, exc_info=True, **kwargs):
         """
         Convenience method for logging an ERROR with exception information.
         """
-        kwargs['exc_info'] = True
-        self.error(msg, *args, **kwargs)
+        self.error(msg, *args, exc_info=exc_info, **kwargs)
 
     def critical(self, msg, *args, **kwargs):
         """
@@ -1402,7 +1401,9 @@ class Logger(Filterer):
         else: # pragma: no cover
             fn, lno, func = "(unknown file)", 0, "(unknown function)"
         if exc_info:
-            if not isinstance(exc_info, tuple):
+            if isinstance(exc_info, BaseException):
+                exc_info = (type(exc_info), exc_info, exc_info.__traceback__)
+            elif not isinstance(exc_info, tuple):
                 exc_info = sys.exc_info()
         record = self.makeRecord(self.name, level, fn, lno, msg, args,
                                  exc_info, func, extra, sinfo)
@@ -1612,12 +1613,11 @@ class LoggerAdapter(object):
         """
         self.log(ERROR, msg, *args, **kwargs)
 
-    def exception(self, msg, *args, **kwargs):
+    def exception(self, msg, *args, exc_info=True, **kwargs):
         """
         Delegate an exception call to the underlying logger.
         """
-        kwargs["exc_info"] = True
-        self.log(ERROR, msg, *args, **kwargs)
+        self.log(ERROR, msg, *args, exc_info=exc_info, **kwargs)
 
     def critical(self, msg, *args, **kwargs):
         """
@@ -1796,14 +1796,13 @@ def error(msg, *args, **kwargs):
         basicConfig()
     root.error(msg, *args, **kwargs)
 
-def exception(msg, *args, **kwargs):
+def exception(msg, *args, exc_info=True, **kwargs):
     """
     Log a message with severity 'ERROR' on the root logger, with exception
     information. If the logger has no handlers, basicConfig() is called to add
     a console handler with a pre-defined format.
     """
-    kwargs['exc_info'] = True
-    error(msg, *args, **kwargs)
+    error(msg, *args, exc_info=exc_info, **kwargs)
 
 def warning(msg, *args, **kwargs):
     """
index 070e6369d1f835c5d1b2303f084c762d6744f383..744238195a2826c37a6d92fd829ccdb3798ddb45 100644 (file)
@@ -3712,6 +3712,19 @@ class LoggerAdapterTest(unittest.TestCase):
         self.assertEqual(record.exc_info,
                          (exc.__class__, exc, exc.__traceback__))
 
+    def test_exception_excinfo(self):
+        try:
+            1 / 0
+        except ZeroDivisionError as e:
+            exc = e
+
+        self.adapter.exception('exc_info test', exc_info=exc)
+
+        self.assertEqual(len(self.recording.records), 1)
+        record = self.recording.records[0]
+        self.assertEqual(record.exc_info,
+                         (exc.__class__, exc, exc.__traceback__))
+
     def test_critical(self):
         msg = 'critical test! %r'
         self.adapter.critical(msg, self.recording)
index ea164798e79316547275edb97b0db1f16a5a6292..3be837d1136ea8a2eafbdd81efd7afaa1772c334 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -132,6 +132,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #20537: logging methods now accept an exception instance as well as a
+  Boolean value or exception tuple. Thanks to Yury Selivanov for the patch.
+
 - Issue #22384: An exception in Tkinter callback no longer crashes the program
   when it is run with pythonw.exe.