https://github.com/python/cpython/commit/76ac2dec7991fdd6b9365689a36922d1c1ae0a38
commit: 76ac2dec7991fdd6b9365689a36922d1c1ae0a38
branch: main
author: Vyron Vasileiadis <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-08-16T08:34:21+03:00
summary:

gh-154002: Do not wrap a constructor TypeError in pickle._Unpickler (GH-154003)

It passed the traceback as the second argument to a new TypeError, so that
the traceback object ended up in args and the original error was not
chained.  The original error now propagates, as in the C implementation.

files:
A Misc/NEWS.d/next/Library/2026-07-18-18-12-44.gh-issue-154002.Qw9zTn.rst
M Lib/pickle.py
M Lib/test/picklecommon.py
M Lib/test/pickletester.py

diff --git a/Lib/pickle.py b/Lib/pickle.py
index f92b1fde768fc7d..b475d96dd6576d9 100644
--- a/Lib/pickle.py
+++ b/Lib/pickle.py
@@ -1623,11 +1623,7 @@ def load_dict(self):
     def _instantiate(self, klass, args):
         if (args or not isinstance(klass, type) or
             hasattr(klass, "__getinitargs__")):
-            try:
-                value = klass(*args)
-            except TypeError as err:
-                raise TypeError("in constructor for %s: %s" %
-                                (klass.__name__, str(err)), err.__traceback__)
+            value = klass(*args)
         else:
             value = klass.__new__(klass)
         self.append(value)
diff --git a/Lib/test/picklecommon.py b/Lib/test/picklecommon.py
index bb8e41b01492ead..5dd56c4fbf9ec81 100644
--- a/Lib/test/picklecommon.py
+++ b/Lib/test/picklecommon.py
@@ -17,6 +17,11 @@ class E(C):
     def __getinitargs__(self):
         return ()
 
+# For test_load_bad_constructor
+class BadConstructor:
+    def __init__(self, *args):
+        raise TypeError("bad constructor")
+
 import __main__
 __main__.C = C
 C.__module__ = "__main__"
@@ -24,6 +29,8 @@ def __getinitargs__(self):
 D.__module__ = "__main__"
 __main__.E = E
 E.__module__ = "__main__"
+__main__.BadConstructor = BadConstructor
+BadConstructor.__module__ = "__main__"
 
 # Simple mutable object.
 class Object(object):
diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
index 83a71b7efedd379..c53262e358b48ea 100644
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -846,6 +846,20 @@ def test_load_classic_instance(self):
                        b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
             self.assert_is_copy(X(*args), self.loads(pickle2))
 
+    def test_load_bad_constructor(self):
+        # gh-154002: a TypeError raised by an old-style instance constructor
+        # during INST/OBJ unpickling propagates unchanged.  The pure-Python
+        # unpickler used to replace it with one that carried the traceback
+        # object in its args.
+        #  0: (    MARK
+        #  1: I        INT        1
+        #  4: i        INST       '__main__ BadConstructor' (MARK at 0)
+        # 28: .    STOP
+        data = b'(I1\ni__main__\nBadConstructor\n.'
+        with self.assertRaises(TypeError) as cm:
+            self.loads(data)
+        self.assertEqual(cm.exception.args, ("bad constructor",))
+
     def test_maxint64(self):
         maxint64 = (1 << 63) - 1
         data = b'I' + str(maxint64).encode("ascii") + b'\n.'
diff --git 
a/Misc/NEWS.d/next/Library/2026-07-18-18-12-44.gh-issue-154002.Qw9zTn.rst 
b/Misc/NEWS.d/next/Library/2026-07-18-18-12-44.gh-issue-154002.Qw9zTn.rst
new file mode 100644
index 000000000000000..0475ce7330b6fa8
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-07-18-18-12-44.gh-issue-154002.Qw9zTn.rst
@@ -0,0 +1,4 @@
+The pure-Python :mod:`pickle` unpickler no longer replaces a :exc:`TypeError`
+raised by an old-style instance constructor with a new one carrying the
+traceback object in its ``args``. The original error now propagates, as it
+already did in the C implementation.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to