mirror of
https://github.com/python/cpython.git
synced 2025-08-31 14:07:50 +00:00
gh-103763: Implement PEP 695 (#103764)
This implements PEP 695, Type Parameter Syntax. It adds support for: - Generic functions (def func[T](): ...) - Generic classes (class X[T](): ...) - Type aliases (type X = ...) - New scoping when the new syntax is used within a class body - Compiler and interpreter changes to support the new syntax and scoping rules Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Co-authored-by: Eric Traut <eric@traut.com> Co-authored-by: Larry Hastings <larry@hastings.org> Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
fdafdc235e
commit
24d8b88420
56 changed files with 11405 additions and 5469 deletions
|
@ -48,11 +48,8 @@ from test import mod_generics_cache
|
|||
from test import _typed_dict_helper
|
||||
|
||||
|
||||
py_typing = import_helper.import_fresh_module('typing', blocked=['_typing'])
|
||||
c_typing = import_helper.import_fresh_module('typing', fresh=['_typing'])
|
||||
|
||||
|
||||
CANNOT_SUBCLASS_TYPE = 'Cannot subclass special typing classes'
|
||||
NOT_A_BASE_TYPE = "type 'typing.%s' is not an acceptable base type"
|
||||
CANNOT_SUBCLASS_INSTANCE = 'Cannot subclass an instance of %s'
|
||||
|
||||
|
||||
|
@ -430,7 +427,7 @@ class TypeVarTests(BaseTestCase):
|
|||
self.assertNotEqual(TypeVar('T', int, str), TypeVar('T', int, str))
|
||||
|
||||
def test_cannot_subclass(self):
|
||||
with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
|
||||
with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'TypeVar'):
|
||||
class V(TypeVar): pass
|
||||
T = TypeVar("T")
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
|
@ -446,6 +443,9 @@ class TypeVarTests(BaseTestCase):
|
|||
TypeVar('X', bound=Union)
|
||||
with self.assertRaises(TypeError):
|
||||
TypeVar('X', str, float, bound=Employee)
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"Bound must be a type\. Got \(1, 2\)\."):
|
||||
TypeVar('X', bound=(1, 2))
|
||||
|
||||
def test_missing__name__(self):
|
||||
# See bpo-39942
|
||||
|
@ -1161,7 +1161,7 @@ class TypeVarTupleTests(BaseTestCase):
|
|||
self.assertEndsWith(repr(K[float, str]), 'A[float, str, typing.Unpack[typing.Tuple[str, ...]]]')
|
||||
|
||||
def test_cannot_subclass(self):
|
||||
with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
|
||||
with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'TypeVarTuple'):
|
||||
class C(TypeVarTuple): pass
|
||||
Ts = TypeVarTuple('Ts')
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
|
@ -6444,34 +6444,27 @@ class TypeTests(BaseTestCase):
|
|||
class TestModules(TestCase):
|
||||
func_names = ['_idfunc']
|
||||
|
||||
def test_py_functions(self):
|
||||
for fname in self.func_names:
|
||||
self.assertEqual(getattr(py_typing, fname).__module__, 'typing')
|
||||
|
||||
@skipUnless(c_typing, 'requires _typing')
|
||||
def test_c_functions(self):
|
||||
for fname in self.func_names:
|
||||
self.assertEqual(getattr(c_typing, fname).__module__, '_typing')
|
||||
self.assertEqual(getattr(typing, fname).__module__, '_typing')
|
||||
|
||||
|
||||
class NewTypeTests:
|
||||
class NewTypeTests(BaseTestCase):
|
||||
def cleanup(self):
|
||||
for f in self.module._cleanups:
|
||||
for f in typing._cleanups:
|
||||
f()
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
sys.modules['typing'] = cls.module
|
||||
global UserId
|
||||
UserId = cls.module.NewType('UserId', int)
|
||||
cls.UserName = cls.module.NewType(cls.__qualname__ + '.UserName', str)
|
||||
UserId = typing.NewType('UserId', int)
|
||||
cls.UserName = typing.NewType(cls.__qualname__ + '.UserName', str)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
global UserId
|
||||
del UserId
|
||||
del cls.UserName
|
||||
sys.modules['typing'] = typing
|
||||
|
||||
def tearDown(self):
|
||||
self.cleanup()
|
||||
|
@ -6491,11 +6484,11 @@ class NewTypeTests:
|
|||
def test_or(self):
|
||||
for cls in (int, self.UserName):
|
||||
with self.subTest(cls=cls):
|
||||
self.assertEqual(UserId | cls, self.module.Union[UserId, cls])
|
||||
self.assertEqual(cls | UserId, self.module.Union[cls, UserId])
|
||||
self.assertEqual(UserId | cls, typing.Union[UserId, cls])
|
||||
self.assertEqual(cls | UserId, typing.Union[cls, UserId])
|
||||
|
||||
self.assertEqual(self.module.get_args(UserId | cls), (UserId, cls))
|
||||
self.assertEqual(self.module.get_args(cls | UserId), (cls, UserId))
|
||||
self.assertEqual(typing.get_args(UserId | cls), (UserId, cls))
|
||||
self.assertEqual(typing.get_args(cls | UserId), (cls, UserId))
|
||||
|
||||
def test_special_attrs(self):
|
||||
self.assertEqual(UserId.__name__, 'UserId')
|
||||
|
@ -6516,7 +6509,7 @@ class NewTypeTests:
|
|||
f'{__name__}.{self.__class__.__qualname__}.UserName')
|
||||
|
||||
def test_pickle(self):
|
||||
UserAge = self.module.NewType('UserAge', float)
|
||||
UserAge = typing.NewType('UserAge', float)
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
with self.subTest(proto=proto):
|
||||
pickled = pickle.dumps(UserId, proto)
|
||||
|
@ -6548,15 +6541,6 @@ class NewTypeTests:
|
|||
...
|
||||
|
||||
|
||||
class NewTypePythonTests(NewTypeTests, BaseTestCase):
|
||||
module = py_typing
|
||||
|
||||
|
||||
@skipUnless(c_typing, 'requires _typing')
|
||||
class NewTypeCTests(NewTypeTests, BaseTestCase):
|
||||
module = c_typing
|
||||
|
||||
|
||||
class NamedTupleTests(BaseTestCase):
|
||||
class NestedEmployee(NamedTuple):
|
||||
name: str
|
||||
|
@ -8170,11 +8154,11 @@ class ParamSpecTests(BaseTestCase):
|
|||
self.assertEqual(C2[Concatenate[T, P2]].__parameters__, (T, P2))
|
||||
|
||||
def test_cannot_subclass(self):
|
||||
with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
|
||||
with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpec'):
|
||||
class C(ParamSpec): pass
|
||||
with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
|
||||
with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpecArgs'):
|
||||
class C(ParamSpecArgs): pass
|
||||
with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE):
|
||||
with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpecKwargs'):
|
||||
class C(ParamSpecKwargs): pass
|
||||
P = ParamSpec('P')
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue