Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Lib/test/test_dataclasses/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def test_field_recursive_repr(self):

self.assertIn(",type=...,", repr_output)

@unittest.expectedFailure # TODO: RUSTPYTHON; recursive annotation type not shown as ...
def test_recursive_annotation(self):
class C:
pass
Expand Down
153 changes: 142 additions & 11 deletions Lib/test/test_genericalias.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@
from weakref import WeakSet, ReferenceType, ref
import typing
from typing import Unpack
try:
from tkinter import Event
except ImportError:
Event = None
from string.templatelib import Template, Interpolation

from typing import TypeVar
T = TypeVar('T')
Expand Down Expand Up @@ -96,7 +101,7 @@

class BaseTest(unittest.TestCase):
"""Test basics."""
generic_types = [type, tuple, list, dict, set, frozenset, enumerate,
generic_types = [type, tuple, list, dict, set, frozenset, enumerate, memoryview,
defaultdict, deque,
SequenceMatcher,
dircmp,
Expand Down Expand Up @@ -133,13 +138,21 @@ class BaseTest(unittest.TestCase):
Future, _WorkItem,
Morsel,
DictReader, DictWriter,
array]
array,
staticmethod,
classmethod,
Template,
Interpolation,
]
if ctypes is not None:
generic_types.extend((ctypes.Array, ctypes.LibraryLoader))
generic_types.extend((ctypes.Array, ctypes.LibraryLoader, ctypes.py_object))
if ValueProxy is not None:
generic_types.extend((ValueProxy, DictProxy, ListProxy, ApplyResult,
MPSimpleQueue, MPQueue, MPJoinableQueue))
if Event is not None:
generic_types.append(Event)

@unittest.expectedFailure # TODO: RUSTPYTHON; memoryview, Template, Interpolation, py_object not subscriptable
def test_subscriptable(self):
for t in self.generic_types:
if t is None:
Expand Down Expand Up @@ -209,7 +222,6 @@ class MyList(list):
self.assertEqual(t.__args__, (int,))
self.assertEqual(t.__parameters__, ())

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_repr(self):
class MyList(list):
pass
Expand All @@ -225,13 +237,63 @@ class MyGeneric:
self.assertEqual(repr(x2), 'tuple[*tuple[int, str]]')
x3 = tuple[*tuple[int, ...]]
self.assertEqual(repr(x3), 'tuple[*tuple[int, ...]]')
self.assertTrue(repr(MyList[int]).endswith('.BaseTest.test_repr.<locals>.MyList[int]'))
self.assertEndsWith(repr(MyList[int]), '.BaseTest.test_repr.<locals>.MyList[int]')
self.assertEqual(repr(list[str]()), '[]') # instances should keep their normal repr

# gh-105488
self.assertTrue(repr(MyGeneric[int]).endswith('MyGeneric[int]'))
self.assertTrue(repr(MyGeneric[[]]).endswith('MyGeneric[[]]'))
self.assertTrue(repr(MyGeneric[[int, str]]).endswith('MyGeneric[[int, str]]'))
self.assertEndsWith(repr(MyGeneric[int]), 'MyGeneric[int]')
self.assertEndsWith(repr(MyGeneric[[]]), 'MyGeneric[[]]')
self.assertEndsWith(repr(MyGeneric[[int, str]]), 'MyGeneric[[int, str]]')

def test_evil_repr1(self):
# gh-143635
class Zap:
def __init__(self, container):
self.container = container
def __getattr__(self, name):
if name == "__origin__":
self.container.clear()
return None
if name == "__args__":
return ()
raise AttributeError

params = []
params.append(Zap(params))
alias = GenericAlias(list, (params,))
repr_str = repr(alias)
self.assertTrue(repr_str.startswith("list[["), repr_str)

def test_evil_repr2(self):
class Zap:
def __init__(self, container):
self.container = container
def __getattr__(self, name):
if name == "__qualname__":
self.container.clear()
return "abcd"
if name == "__module__":
return None
raise AttributeError

params = []
params.append(Zap(params))
alias = GenericAlias(list, (params,))
repr_str = repr(alias)
self.assertTrue(repr_str.startswith("list[["), repr_str)

def test_evil_repr3(self):
# gh-143823
lst = []
class X:
def __repr__(self):
lst.clear()
return "x"

lst += [X(), 1]
ga = GenericAlias(int, lst)
with self.assertRaises(IndexError):
repr(ga)

def test_exposed_type(self):
import types
Expand Down Expand Up @@ -333,7 +395,6 @@ def test_parameter_chaining(self):
with self.assertRaises(TypeError):
dict[T, T][str, int]

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_equality(self):
self.assertEqual(list[int], list[int])
self.assertEqual(dict[str, int], dict[str, int])
Expand All @@ -352,7 +413,7 @@ def test_isinstance(self):

def test_issubclass(self):
class L(list): ...
self.assertTrue(issubclass(L, list))
self.assertIsSubclass(L, list)
with self.assertRaises(TypeError):
issubclass(L, list[str])

Expand Down Expand Up @@ -424,7 +485,6 @@ def test_union_generic(self):
self.assertEqual(a.__args__, (list[T], tuple[T, ...]))
self.assertEqual(a.__parameters__, (T,))

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_dir(self):
ga = list[int]
dir_of_gen_alias = set(dir(ga))
Expand All @@ -447,6 +507,7 @@ def test_dir(self):
with self.subTest(entry=entry):
getattr(ga, entry) # must not raise `AttributeError`

@unittest.expectedFailure # TODO: RUSTPYTHON; memoryview, Template, Interpolation, py_object not subscriptable
def test_weakref(self):
for t in self.generic_types:
if t is None:
Expand Down Expand Up @@ -490,6 +551,76 @@ def test_del_iter(self):
iter_x = iter(t)
del iter_x

def test_paramspec_specialization(self):
# gh-124445
T = TypeVar("T")
U = TypeVar("U")
type X[**P] = Callable[P, int]

generic = X[[T]]
self.assertEqual(generic.__args__, ([T],))
self.assertEqual(generic.__parameters__, (T,))
specialized = generic[str]
self.assertEqual(specialized.__args__, ([str],))
self.assertEqual(specialized.__parameters__, ())

generic = X[(T,)]
self.assertEqual(generic.__args__, (T,))
self.assertEqual(generic.__parameters__, (T,))
specialized = generic[str]
self.assertEqual(specialized.__args__, (str,))
self.assertEqual(specialized.__parameters__, ())

generic = X[[T, U]]
self.assertEqual(generic.__args__, ([T, U],))
self.assertEqual(generic.__parameters__, (T, U))
specialized = generic[str, int]
self.assertEqual(specialized.__args__, ([str, int],))
self.assertEqual(specialized.__parameters__, ())

generic = X[(T, U)]
self.assertEqual(generic.__args__, (T, U))
self.assertEqual(generic.__parameters__, (T, U))
specialized = generic[str, int]
self.assertEqual(specialized.__args__, (str, int))
self.assertEqual(specialized.__parameters__, ())

def test_nested_paramspec_specialization(self):
# gh-124445
type X[**P, T] = Callable[P, T]

x_list = X[[int, str], float]
self.assertEqual(x_list.__args__, ([int, str], float))
self.assertEqual(x_list.__parameters__, ())

x_tuple = X[(int, str), float]
self.assertEqual(x_tuple.__args__, ((int, str), float))
self.assertEqual(x_tuple.__parameters__, ())

U = TypeVar("U")
V = TypeVar("V")

multiple_params_list = X[[int, U], V]
self.assertEqual(multiple_params_list.__args__, ([int, U], V))
self.assertEqual(multiple_params_list.__parameters__, (U, V))
multiple_params_list_specialized = multiple_params_list[str, float]
self.assertEqual(multiple_params_list_specialized.__args__, ([int, str], float))
self.assertEqual(multiple_params_list_specialized.__parameters__, ())

multiple_params_tuple = X[(int, U), V]
self.assertEqual(multiple_params_tuple.__args__, ((int, U), V))
self.assertEqual(multiple_params_tuple.__parameters__, (U, V))
multiple_params_tuple_specialized = multiple_params_tuple[str, float]
self.assertEqual(multiple_params_tuple_specialized.__args__, ((int, str), float))
self.assertEqual(multiple_params_tuple_specialized.__parameters__, ())

deeply_nested = X[[U, [V], int], V]
self.assertEqual(deeply_nested.__args__, ([U, [V], int], V))
self.assertEqual(deeply_nested.__parameters__, (U, V))
deeply_nested_specialized = deeply_nested[str, float]
self.assertEqual(deeply_nested_specialized.__args__, ([str, [float], int], float))
self.assertEqual(deeply_nested_specialized.__parameters__, ())


class TypeIterationTests(unittest.TestCase):
_UNITERABLE_TYPES = (list, tuple)
Expand Down
1 change: 0 additions & 1 deletion Lib/test/test_reprlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,6 @@ def __repr__(self):

self.assertIs(X.f, X.__repr__.__wrapped__)

@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'TypeVar' object has no attribute '__name__'
def test__type_params__(self):
class My:
@recursive_repr()
Expand Down
Loading