Skip to content

Commit b2764c9

Browse files
committed
Deserialize by using __new__ instead of constructor if possible
Exception to IOError is because this built-in exception is assigning internal myerrno attribute in __init__ constructor and cannot be changed from Python code. Fixes: #65 Signed-off-by: Oldřich Jedlička <[email protected]>
1 parent 1e5a2e6 commit b2764c9

File tree

1 file changed

+21
-1
lines changed

1 file changed

+21
-1
lines changed

src/tblib/pickling_support.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import copyreg
22
from functools import partial
3+
from types import BuiltinFunctionType
34
from types import TracebackType
45

56
from . import Frame
@@ -22,6 +23,19 @@ def pickle_traceback(tb, *, get_locals=None):
2223
)
2324

2425

26+
def unpickle_builtin_exception(func, args, cause, tb, context, suppress_context, notes):
27+
inst = func.__new__(func)
28+
if args is not None:
29+
inst.args = args
30+
inst.__cause__ = cause
31+
inst.__traceback__ = tb
32+
inst.__context__ = context
33+
inst.__suppress_context__ = suppress_context
34+
if notes is not None:
35+
inst.__notes__ = notes
36+
return inst
37+
38+
2539
# Note: Older versions of tblib will generate pickle archives that call unpickle_exception() with
2640
# fewer arguments. We assign default values to some of the arguments to support this.
2741
def unpickle_exception(func, args, cause, tb, context=None, suppress_context=False, notes=None):
@@ -49,8 +63,14 @@ def pickle_exception(obj):
4963
assert isinstance(rv, tuple)
5064
assert len(rv) >= 2
5165

66+
use_builtin = (
67+
isinstance(obj.__reduce_ex__, BuiltinFunctionType)
68+
and isinstance(obj.__reduce__, BuiltinFunctionType)
69+
and not isinstance(obj, IOError)
70+
)
71+
5272
return (
53-
unpickle_exception,
73+
unpickle_builtin_exception if use_builtin else unpickle_exception,
5474
rv[:2]
5575
+ (
5676
obj.__cause__,

0 commit comments

Comments
 (0)