summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/inspect.py20
-rw-r--r--Lib/test/test_inspect.py53
2 files changed, 73 insertions, 0 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py
index 6054c39..bce0516 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -2106,6 +2106,18 @@ class Parameter:
self._partial_kwarg = _partial_kwarg
+ def __reduce__(self):
+ return (type(self),
+ (self._name, self._kind),
+ {'_partial_kwarg': self._partial_kwarg,
+ '_default': self._default,
+ '_annotation': self._annotation})
+
+ def __setstate__(self, state):
+ self._partial_kwarg = state['_partial_kwarg']
+ self._default = state['_default']
+ self._annotation = state['_annotation']
+
@property
def name(self):
return self._name
@@ -2658,6 +2670,14 @@ class Signature:
'''
return args[0]._bind(args[1:], kwargs, partial=True)
+ def __reduce__(self):
+ return (type(self),
+ (tuple(self._parameters.values()),),
+ {'_return_annotation': self._return_annotation})
+
+ def __setstate__(self, state):
+ self._return_annotation = state['_return_annotation']
+
def __str__(self):
result = []
render_pos_only_separator = False
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index 5c6ae39..373bd4c 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -8,6 +8,7 @@ import linecache
import os
from os.path import normcase
import _pickle
+import pickle
import re
import shutil
import sys
@@ -73,6 +74,7 @@ def generator_function_example(self):
for i in range(2):
yield i
+
class TestPredicates(IsTestBase):
def test_sixteen(self):
count = len([x for x in dir(inspect) if x.startswith('is')])
@@ -1597,6 +1599,17 @@ class TestGetGeneratorState(unittest.TestCase):
self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
+class MySignature(inspect.Signature):
+ # Top-level to make it picklable;
+ # used in test_signature_object_pickle
+ pass
+
+class MyParameter(inspect.Parameter):
+ # Top-level to make it picklable;
+ # used in test_signature_object_pickle
+ pass
+
+
class TestSignatureObject(unittest.TestCase):
@staticmethod
def signature(func):
@@ -1654,6 +1667,36 @@ class TestSignatureObject(unittest.TestCase):
with self.assertRaisesRegex(ValueError, 'follows default argument'):
S((pkd, pk))
+ def test_signature_object_pickle(self):
+ def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
+ foo_partial = functools.partial(foo, a=1)
+
+ sig = inspect.signature(foo_partial)
+ self.assertTrue(sig.parameters['a']._partial_kwarg)
+
+ for ver in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.subTest(pickle_ver=ver, subclass=False):
+ sig_pickled = pickle.loads(pickle.dumps(sig, ver))
+ self.assertEqual(sig, sig_pickled)
+ self.assertTrue(sig_pickled.parameters['a']._partial_kwarg)
+
+ # Test that basic sub-classing works
+ sig = inspect.signature(foo)
+ myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
+ myparams = collections.OrderedDict(sig.parameters, a=myparam)
+ mysig = MySignature().replace(parameters=myparams.values(),
+ return_annotation=sig.return_annotation)
+ self.assertTrue(isinstance(mysig, MySignature))
+ self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
+
+ for ver in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.subTest(pickle_ver=ver, subclass=True):
+ sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
+ self.assertEqual(mysig, sig_pickled)
+ self.assertTrue(isinstance(sig_pickled, MySignature))
+ self.assertTrue(isinstance(sig_pickled.parameters['z'],
+ MyParameter))
+
def test_signature_immutability(self):
def test(a):
pass
@@ -2845,6 +2888,16 @@ class TestBoundArguments(unittest.TestCase):
ba4 = inspect.signature(bar).bind(1)
self.assertNotEqual(ba, ba4)
+ def test_signature_bound_arguments_pickle(self):
+ def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
+ sig = inspect.signature(foo)
+ ba = sig.bind(20, 30, z={})
+
+ for ver in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.subTest(pickle_ver=ver):
+ ba_pickled = pickle.loads(pickle.dumps(ba, ver))
+ self.assertEqual(ba, ba_pickled)
+
class TestSignaturePrivateHelpers(unittest.TestCase):
def test_signature_get_bound_param(self):