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

Lines changed: 65 additions & 4 deletions
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

Lines changed: 66 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy