Skip to content

Commit 211dcff

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 211dcff

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

src/tblib/pickling_support.py

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import copyreg
22
from functools import partial
3-
from types import TracebackType
3+
from types import BuiltinFunctionType, TracebackType
44

55
from . import Frame
66
from . import Traceback
@@ -22,6 +22,19 @@ def pickle_traceback(tb, *, get_locals=None):
2222
)
2323

2424

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

65+
use_builtin = isinstance(obj.__reduce_ex__, BuiltinFunctionType) and \
66+
isinstance(obj.__reduce__, BuiltinFunctionType) and \
67+
not isinstance(obj, IOError)
68+
5269
return (
53-
unpickle_exception,
70+
unpickle_builtin_exception if use_builtin else unpickle_exception,
5471
rv[:2]
5572
+ (
5673
obj.__cause__,

0 commit comments

Comments
 (0)