gh-105433: Add `pickle` tests for PEP695 (#105443)

This commit is contained in:
Nikita Sobolev 2023-06-16 03:58:40 +03:00 committed by GitHub
parent 486b52a315
commit 1af8251d9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 131 additions and 4 deletions

View File

@ -228,8 +228,69 @@ class TypeAliasTypeTest(unittest.TestCase):
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],
ConstrainedGenericAlias,
ConstrainedGenericAlias[str],
ConstrainedGenericAlias[T],
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)

View File

@ -2,6 +2,7 @@ import asyncio
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
@ -855,3 +856,68 @@ class TypeParamsTypeParamsDunder(unittest.TestCase):
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_functions(self):
things_to_test = [
func1,
func2,
func3,
func4,
]
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)
def test_pickling_classes(self):
things_to_test = [
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, bytes],
Class4[int, T],
Class4[T, T],
]
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)
for klass in things_to_test:
real_class = getattr(klass, '__origin__', klass)
thing = klass()
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.subTest(thing=thing, proto=proto):
pickled = pickle.dumps(thing, protocol=proto)
# These instances are not equal,
# but class check is good enough:
self.assertIsInstance(pickle.loads(pickled), real_class)