summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikita Sobolev <mail@sobolevn.me>2023-06-16 00:58:40 (GMT)
committerGitHub <noreply@github.com>2023-06-16 00:58:40 (GMT)
commit1af8251d9ec2f18e131c19ccf776fb9ec132c7a8 (patch)
tree6b9752b607f6d04d243b7aaed5b31ff0d14876d4
parent486b52a3158e0f64fc54efdfa34ed5437b3619f2 (diff)
downloadcpython-1af8251d9ec2f18e131c19ccf776fb9ec132c7a8.zip
cpython-1af8251d9ec2f18e131c19ccf776fb9ec132c7a8.tar.gz
cpython-1af8251d9ec2f18e131c19ccf776fb9ec132c7a8.tar.bz2
gh-105433: Add `pickle` tests for PEP695 (#105443)
-rw-r--r--Lib/test/test_type_aliases.py69
-rw-r--r--Lib/test/test_type_params.py66
2 files changed, 131 insertions, 4 deletions
diff --git a/Lib/test/test_type_aliases.py b/Lib/test/test_type_aliases.py
index a3067e5..b9b2444 100644
--- a/Lib/test/test_type_aliases.py
+++ b/Lib/test/test_type_aliases.py
@@ -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)
diff --git a/Lib/test/test_type_params.py b/Lib/test/test_type_params.py
index 6475df6..3026cc2 100644
--- a/Lib/test/test_type_params.py
+++ b/Lib/test/test_type_params.py
@@ -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)