Skip to content

Commit 1af8251

Browse files
authored
gh-105433: Add pickle tests for PEP695 (#105443)
1 parent 486b52a commit 1af8251

File tree

2 files changed

+131
-4
lines changed

2 files changed

+131
-4
lines changed

Lib/test/test_type_aliases.py

+65-4
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,69 @@ def test_module(self):
228228
self.assertEqual(mod_generics_cache.OldStyle.__module__,
229229
mod_generics_cache.__name__)
230230

231+
232+
# All these type aliases are used for pickling tests:
233+
T = TypeVar('T')
234+
type SimpleAlias = int
235+
type RecursiveAlias = dict[str, RecursiveAlias]
236+
type GenericAlias[X] = list[X]
237+
type GenericAliasMultipleTypes[X, Y] = dict[X, Y]
238+
type RecursiveGenericAlias[X] = dict[str, RecursiveAlias[X]]
239+
type BoundGenericAlias[X: int] = set[X]
240+
type ConstrainedGenericAlias[LongName: (str, bytes)] = list[LongName]
241+
type AllTypesAlias[A, *B, **C] = Callable[C, A] | tuple[*B]
242+
243+
244+
class TypeAliasPickleTest(unittest.TestCase):
231245
def test_pickling(self):
232-
pickled = pickle.dumps(mod_generics_cache.Alias)
233-
self.assertIs(pickle.loads(pickled), mod_generics_cache.Alias)
234-
pickled = pickle.dumps(mod_generics_cache.OldStyle)
235-
self.assertIs(pickle.loads(pickled), mod_generics_cache.OldStyle)
246+
things_to_test = [
247+
SimpleAlias,
248+
RecursiveAlias,
249+
250+
GenericAlias,
251+
GenericAlias[T],
252+
GenericAlias[int],
253+
254+
GenericAliasMultipleTypes,
255+
GenericAliasMultipleTypes[str, T],
256+
GenericAliasMultipleTypes[T, str],
257+
GenericAliasMultipleTypes[int, str],
258+
259+
RecursiveGenericAlias,
260+
RecursiveGenericAlias[T],
261+
RecursiveGenericAlias[int],
262+
263+
BoundGenericAlias,
264+
BoundGenericAlias[int],
265+
BoundGenericAlias[T],
266+
267+
ConstrainedGenericAlias,
268+
ConstrainedGenericAlias[str],
269+
ConstrainedGenericAlias[T],
270+
271+
AllTypesAlias,
272+
AllTypesAlias[int, str, T, [T, object]],
273+
274+
# Other modules:
275+
mod_generics_cache.Alias,
276+
mod_generics_cache.OldStyle,
277+
]
278+
for thing in things_to_test:
279+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
280+
with self.subTest(thing=thing, proto=proto):
281+
pickled = pickle.dumps(thing, protocol=proto)
282+
self.assertEqual(pickle.loads(pickled), thing)
283+
284+
type ClassLevel = str
285+
286+
def test_pickling_local(self):
287+
type A = int
288+
things_to_test = [
289+
self.ClassLevel,
290+
A,
291+
]
292+
for thing in things_to_test:
293+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
294+
with self.subTest(thing=thing, proto=proto):
295+
with self.assertRaises(pickle.PickleError):
296+
pickle.dumps(thing, protocol=proto)

Lib/test/test_type_params.py

+66
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import textwrap
33
import types
44
import unittest
5+
import pickle
56
from test.support import requires_working_socket, check_syntax_error, run_code
67

78
from typing import Generic, Sequence, TypeVar, TypeVarTuple, ParamSpec, get_args
@@ -855,3 +856,68 @@ def func[A]():
855856

856857
ns = run_code(code)
857858
self.assertEqual(ns["func"].__type_params__, ())
859+
860+
861+
862+
# All these type aliases are used for pickling tests:
863+
T = TypeVar('T')
864+
def func1[X](x: X) -> X: ...
865+
def func2[X, Y](x: X | Y) -> X | Y: ...
866+
def func3[X, *Y, **Z](x: X, y: tuple[*Y], z: Z) -> X: ...
867+
def func4[X: int, Y: (bytes, str)](x: X, y: Y) -> X | Y: ...
868+
869+
class Class1[X]: ...
870+
class Class2[X, Y]: ...
871+
class Class3[X, *Y, **Z]: ...
872+
class Class4[X: int, Y: (bytes, str)]: ...
873+
874+
875+
class TypeParamsPickleTest(unittest.TestCase):
876+
def test_pickling_functions(self):
877+
things_to_test = [
878+
func1,
879+
func2,
880+
func3,
881+
func4,
882+
]
883+
for thing in things_to_test:
884+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
885+
with self.subTest(thing=thing, proto=proto):
886+
pickled = pickle.dumps(thing, protocol=proto)
887+
self.assertEqual(pickle.loads(pickled), thing)
888+
889+
def test_pickling_classes(self):
890+
things_to_test = [
891+
Class1,
892+
Class1[int],
893+
Class1[T],
894+
895+
Class2,
896+
Class2[int, T],
897+
Class2[T, int],
898+
Class2[int, str],
899+
900+
Class3,
901+
Class3[int, T, str, bytes, [float, object, T]],
902+
903+
Class4,
904+
Class4[int, bytes],
905+
Class4[T, bytes],
906+
Class4[int, T],
907+
Class4[T, T],
908+
]
909+
for thing in things_to_test:
910+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
911+
with self.subTest(thing=thing, proto=proto):
912+
pickled = pickle.dumps(thing, protocol=proto)
913+
self.assertEqual(pickle.loads(pickled), thing)
914+
915+
for klass in things_to_test:
916+
real_class = getattr(klass, '__origin__', klass)
917+
thing = klass()
918+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
919+
with self.subTest(thing=thing, proto=proto):
920+
pickled = pickle.dumps(thing, protocol=proto)
921+
# These instances are not equal,
922+
# but class check is good enough:
923+
self.assertIsInstance(pickle.loads(pickled), real_class)

0 commit comments

Comments
 (0)