PEP 415: Implement suppression of __context__ display with an exception attribute

This replaces the original PEP 409 implementation. See #14133.
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index 39ff85f..97762f9 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -388,18 +388,18 @@
     def testChainingAttrs(self):
         e = Exception()
         self.assertIsNone(e.__context__)
-        self.assertIs(e.__cause__, Ellipsis)
+        self.assertIsNone(e.__cause__)
 
         e = TypeError()
         self.assertIsNone(e.__context__)
-        self.assertIs(e.__cause__, Ellipsis)
+        self.assertIsNone(e.__cause__)
 
         class MyException(EnvironmentError):
             pass
 
         e = MyException()
         self.assertIsNone(e.__context__)
-        self.assertIs(e.__cause__, Ellipsis)
+        self.assertIsNone(e.__cause__)
 
     def testChainingDescriptors(self):
         try:
@@ -408,15 +408,16 @@
             e = exc
 
         self.assertIsNone(e.__context__)
-        self.assertIs(e.__cause__, Ellipsis)
+        self.assertIsNone(e.__cause__)
+        self.assertFalse(e.__suppress_context__)
 
         e.__context__ = NameError()
         e.__cause__ = None
         self.assertIsInstance(e.__context__, NameError)
         self.assertIsNone(e.__cause__)
-
-        e.__cause__ = Ellipsis
-        self.assertIs(e.__cause__, Ellipsis)
+        self.assertTrue(e.__suppress_context__)
+        e.__suppress_context__ = False
+        self.assertFalse(e.__suppress_context__)
 
     def testKeywordArgs(self):
         # test that builtin exception don't take keyword args,
diff --git a/Lib/test/test_raise.py b/Lib/test/test_raise.py
index 8ae9210..b169867 100644
--- a/Lib/test/test_raise.py
+++ b/Lib/test/test_raise.py
@@ -174,11 +174,14 @@
                     raise ValueError from None
             except ValueError as exc:
                 self.assertIsNone(exc.__cause__)
-                raise exc from Ellipsis
+                self.assertTrue(exc.__suppress_context__)
+                exc.__suppress_context__ = False
+                raise exc
         except ValueError as exc:
             e = exc
 
-        self.assertIs(e.__cause__, Ellipsis)
+        self.assertIsNone(e.__cause__)
+        self.assertFalse(e.__suppress_context__)
         self.assertIsInstance(e.__context__, TypeError)
 
     def test_invalid_cause(self):
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index 2b9abfc..71dbd29 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -700,14 +700,14 @@
         class C(object): pass
         check(C.__dict__, size(h + 'P'))
         # BaseException
-        check(BaseException(), size(h + '5P'))
+        check(BaseException(), size(h + '5Pi'))
         # UnicodeEncodeError
-        check(UnicodeEncodeError("", "", 0, 0, ""), size(h + '5P 2P2PP'))
+        check(UnicodeEncodeError("", "", 0, 0, ""), size(h + '5Pi 2P2PP'))
         # UnicodeDecodeError
         # XXX
 #        check(UnicodeDecodeError("", "", 0, 0, ""), size(h + '5P2PP'))
         # UnicodeTranslateError
-        check(UnicodeTranslateError("", 0, 1, ""), size(h + '5P 2P2PP'))
+        check(UnicodeTranslateError("", 0, 1, ""), size(h + '5Pi 2P2PP'))
         # ellipses
         check(Ellipsis, size(h + ''))
         # EncodingMap
diff --git a/Lib/traceback.py b/Lib/traceback.py
index 35858af..eeb9e73 100644
--- a/Lib/traceback.py
+++ b/Lib/traceback.py
@@ -119,15 +119,16 @@
         seen = set()
     seen.add(exc)
     its = []
+    context = exc.__context__
     cause = exc.__cause__
-    if cause is Ellipsis:
-        context = exc.__context__
-        if context is not None and context not in seen:
-            its.append(_iter_chain(context, None, seen))
-            its.append([(_context_message, None)])
-    elif cause is not None and cause not in seen:
+    if cause is not None and cause not in seen:
         its.append(_iter_chain(cause, False, seen))
         its.append([(_cause_message, None)])
+    elif (context is not None and
+          not exc.__suppress_context__ and
+          context not in seen):
+        its.append(_iter_chain(context, None, seen))
+        its.append([(_context_message, None)])
     its.append([(exc, custom_tb or exc.__traceback__)])
     # itertools.chain is in an extension module and may be unavailable
     for it in its: