Skip to content

Commit

Permalink
pythongh-105433: Add pickle tests for PEP695
Browse files Browse the repository at this point in the history
  • Loading branch information
sobolevn committed Jun 7, 2023
1 parent 27c68a6 commit 15b0172
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 4 deletions.
69 changes: 65 additions & 4 deletions Lib/test/test_type_aliases.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,69 @@ def test_module(self):
self.assertEqual(mod_generics_cache.OldStyle.__module__,
mod_generics_cache.__name__)


# All these type aliases are used for pickling tests:
T = TypeVar('T')
type SimpleAlias = int
type RecursiveAlias = dict[str, RecursiveAlias]
type GenericAlias[X] = list[X]
type GenericAliasMultipleTypes[X, Y] = dict[X, Y]
type RecursiveGenericAlias[X] = dict[str, RecursiveAlias[X]]
type BoundGenericAlias[X: int] = set[X]
type ConstrainedGenericAlias[LongName: (str, bytes)] = list[LongName]
type AllTypesAlias[A, *B, **C] = Callable[C, A] | tuple[*B]


class TypeAliasPickleTest(unittest.TestCase):
def test_pickling(self):
pickled = pickle.dumps(mod_generics_cache.Alias)
self.assertIs(pickle.loads(pickled), mod_generics_cache.Alias)
pickled = pickle.dumps(mod_generics_cache.OldStyle)
self.assertIs(pickle.loads(pickled), mod_generics_cache.OldStyle)
things_to_test = [
SimpleAlias,
RecursiveAlias,

GenericAlias,
GenericAlias[T],
GenericAlias[int],

GenericAliasMultipleTypes,
GenericAliasMultipleTypes[str, T],
GenericAliasMultipleTypes[T, str],
GenericAliasMultipleTypes[int, str],

RecursiveGenericAlias,
RecursiveGenericAlias[T],
RecursiveGenericAlias[int],

BoundGenericAlias,
BoundGenericAlias[int],
BoundGenericAlias[T], # type-checker won't be happy

ConstrainedGenericAlias,
ConstrainedGenericAlias[str],
ConstrainedGenericAlias[T], # type-checker won't be happy

AllTypesAlias,
AllTypesAlias[int, str, T, [T, object]],

# Other modules:
mod_generics_cache.Alias,
mod_generics_cache.OldStyle,
]
for thing in things_to_test:
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.subTest(thing=thing, proto=proto):
pickled = pickle.dumps(thing, protocol=proto)
self.assertEqual(pickle.loads(pickled), thing)

type ClassLevel = str

def test_pickling_local(self):
type A = int
things_to_test = [
self.ClassLevel,
A,
]
for thing in things_to_test:
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.subTest(thing=thing, proto=proto):
with self.assertRaises(pickle.PickleError):
pickle.dumps(thing, protocol=proto)
46 changes: 46 additions & 0 deletions Lib/test/test_type_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import textwrap
import types
import unittest
import pickle
from test.support import requires_working_socket, check_syntax_error, run_code

from typing import Generic, Sequence, TypeVar, TypeVarTuple, ParamSpec, get_args
Expand Down Expand Up @@ -849,3 +850,48 @@ def func[A]():

ns = run_code(code)
self.assertEqual(ns["func"].__type_params__, ())



# All these type aliases are used for pickling tests:
T = TypeVar('T')
def func1[X](x: X) -> X: ...
def func2[X, Y](x: X | Y) -> X | Y: ...
def func3[X, *Y, **Z](x: X, y: tuple[*Y], z: Z) -> X: ...
def func4[X: int, Y: (bytes, str)](x: X, y: Y) -> X | Y: ...

class Class1[X]: ...
class Class2[X, Y]: ...
class Class3[X, *Y, **Z]: ...
class Class4[X: int, Y: (bytes, str)]: ...


class TypeParamsPickleTest(unittest.TestCase):
def test_pickling(self):
things_to_test = [
func1,
func2,
func3,
func4,

Class1,
Class1[int],
Class1[T],

Class2,
Class2[int, T],
Class2[T, int],
Class2[int, str],

Class3,
Class3[int, T, str, bytes, [float, object, T]],

Class4,
Class4[int, bytes],
Class4[T, T], # type-checker won't be happy
]
for thing in things_to_test:
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.subTest(thing=thing, proto=proto):
pickled = pickle.dumps(thing, protocol=proto)
self.assertEqual(pickle.loads(pickled), thing)

0 comments on commit 15b0172

Please sign in to comment.