[Python-checkins] [3.10] bpo-23556: [doc] Fix inaccuracy in documentation for raise without args. Improve tests for context in nested except handlers. (GH-29236) (GH-30953)

miss-islington webhook-mailer at python.org
Thu Jan 27 05:51:11 EST 2022


https://github.com/python/cpython/commit/2572c670d42887e4b1d2475b8da2e9bf6e0aa558
commit: 2572c670d42887e4b1d2475b8da2e9bf6e0aa558
branch: 3.10
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: miss-islington <31488909+miss-islington at users.noreply.github.com>
date: 2022-01-27T02:51:06-08:00
summary:

[3.10] bpo-23556: [doc] Fix inaccuracy in documentation for raise without args. Improve tests for context in nested except handlers.  (GH-29236) (GH-30953)



(cherry picked from commit 08c0ed2d9c0d01ad1a5adc0787bc75e4e90cbb85)


Co-authored-by: Kinshuk Dua <kinshukdua at gmail.com>

Automerge-Triggered-By: GH:iritkatriel

files:
M Doc/library/exceptions.rst
M Doc/reference/simple_stmts.rst
M Lib/test/test_raise.py

diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst
index f8a692e812791..2f97bb8131d78 100644
--- a/Doc/library/exceptions.rst
+++ b/Doc/library/exceptions.rst
@@ -38,15 +38,14 @@ information on defining exceptions is available in the Python Tutorial under
 Exception context
 -----------------
 
-When raising (or re-raising) an exception in an :keyword:`except` or
-:keyword:`finally` clause
-:attr:`__context__` is automatically set to the last exception caught; if the
-new exception is not handled the traceback that is eventually displayed will
-include the originating exception(s) and the final exception.
-
-When raising a new exception (rather than using a bare ``raise`` to re-raise
-the exception currently being handled), the implicit exception context can be
-supplemented with an explicit cause by using :keyword:`from<raise>` with
+When raising a new exception while another exception
+is already being handled, the new exception's
+:attr:`__context__` attribute is automatically set to the handled
+exception.  An exception may be handled when an :keyword:`except` or
+:keyword:`finally` clause, or a :keyword:`with` statement, is used.
+
+This implicit exception context can be
+supplemented with an explicit cause by using :keyword:`!from` with
 :keyword:`raise`::
 
    raise new_exc from original_exc
diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst
index bb1209dfc33be..92dfcb0461e60 100644
--- a/Doc/reference/simple_stmts.rst
+++ b/Doc/reference/simple_stmts.rst
@@ -563,10 +563,10 @@ The :keyword:`!raise` statement
 .. productionlist:: python-grammar
    raise_stmt: "raise" [`expression` ["from" `expression`]]
 
-If no expressions are present, :keyword:`raise` re-raises the last exception
-that was active in the current scope.  If no exception is active in the current
-scope, a :exc:`RuntimeError` exception is raised indicating that this is an
-error.
+If no expressions are present, :keyword:`raise` re-raises the
+exception that is currently being handled, which is also known as the *active exception*.
+If there isn't currently an active exception, a :exc:`RuntimeError` exception is raised
+indicating that this is an error.
 
 Otherwise, :keyword:`raise` evaluates the first expression as the exception
 object.  It must be either a subclass or an instance of :class:`BaseException`.
@@ -581,8 +581,8 @@ The :dfn:`type` of the exception is the exception instance's class, the
 A traceback object is normally created automatically when an exception is raised
 and attached to it as the :attr:`__traceback__` attribute, which is writable.
 You can create an exception and set your own traceback in one step using the
-:meth:`with_traceback` exception method (which returns the same exception
-instance, with its traceback set to its argument), like so::
+:meth:`~BaseException.with_traceback` exception method (which returns the
+same exception instance, with its traceback set to its argument), like so::
 
    raise Exception("foo occurred").with_traceback(tracebackobj)
 
@@ -614,8 +614,10 @@ exceptions will be printed::
      File "<stdin>", line 4, in <module>
    RuntimeError: Something bad happened
 
-A similar mechanism works implicitly if an exception is raised inside an
-exception handler or a :keyword:`finally` clause: the previous exception is then
+A similar mechanism works implicitly if a new exception is raised when
+an exception is already being handled.  An exception may be handled
+when an :keyword:`except` or :keyword:`finally` clause, or a
+:keyword:`with` statement, is used.  The previous exception is then
 attached as the new exception's :attr:`__context__` attribute::
 
    >>> try:
diff --git a/Lib/test/test_raise.py b/Lib/test/test_raise.py
index 8225504c4756d..5936d7535edd5 100644
--- a/Lib/test/test_raise.py
+++ b/Lib/test/test_raise.py
@@ -303,7 +303,7 @@ def test_instance_context_instance_raise(self):
             except:
                 raise OSError()
         except OSError as e:
-            self.assertEqual(e.__context__, context)
+            self.assertIs(e.__context__, context)
         else:
             self.fail("No exception raised")
 
@@ -315,7 +315,7 @@ def test_class_context_instance_raise(self):
             except:
                 raise OSError()
         except OSError as e:
-            self.assertNotEqual(e.__context__, context)
+            self.assertIsNot(e.__context__, context)
             self.assertIsInstance(e.__context__, context)
         else:
             self.fail("No exception raised")
@@ -328,7 +328,7 @@ def test_class_context_class_raise(self):
             except:
                 raise OSError
         except OSError as e:
-            self.assertNotEqual(e.__context__, context)
+            self.assertIsNot(e.__context__, context)
             self.assertIsInstance(e.__context__, context)
         else:
             self.fail("No exception raised")
@@ -415,6 +415,22 @@ def test_reraise_cycle_broken(self):
         except NameError as e:
             self.assertIsNone(e.__context__.__context__)
 
+    def test_not_last(self):
+        # Context is not necessarily the last exception
+        context = Exception("context")
+        try:
+            raise context
+        except Exception:
+            try:
+                raise Exception("caught")
+            except Exception:
+                pass
+            try:
+                raise Exception("new")
+            except Exception as exc:
+                raised = exc
+        self.assertIs(raised.__context__, context)
+
     def test_3118(self):
         # deleting the generator caused the __context__ to be cleared
         def gen():



More information about the Python-checkins mailing list