Skip to content

Commit 500b002

Browse files
authored
updated _collections_abc.py and test_collections.py to CPython 3.11.2 (RustPython#5016)
* updated _collections_abc.py and its tests in test_collections.py * decorated failing tests in test_typing.py
1 parent 4bec66e commit 500b002

File tree

3 files changed

+50
-74
lines changed

3 files changed

+50
-74
lines changed

Lib/_collections_abc.py

Lines changed: 13 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -430,25 +430,13 @@ def __new__(cls, origin, args):
430430
raise TypeError(
431431
"Callable must be used as Callable[[arg, ...], result].")
432432
t_args, t_result = args
433-
if isinstance(t_args, list):
433+
if isinstance(t_args, (tuple, list)):
434434
args = (*t_args, t_result)
435435
elif not _is_param_expr(t_args):
436436
raise TypeError(f"Expected a list of types, an ellipsis, "
437437
f"ParamSpec, or Concatenate. Got {t_args}")
438438
return super().__new__(cls, origin, args)
439439

440-
@property
441-
def __parameters__(self):
442-
params = []
443-
for arg in self.__args__:
444-
# Looks like a genericalias
445-
if hasattr(arg, "__parameters__") and isinstance(arg.__parameters__, tuple):
446-
params.extend(arg.__parameters__)
447-
else:
448-
if _is_typevarlike(arg):
449-
params.append(arg)
450-
return tuple(dict.fromkeys(params))
451-
452440
def __repr__(self):
453441
if len(self.__args__) == 2 and _is_param_expr(self.__args__[0]):
454442
return super().__repr__()
@@ -468,54 +456,24 @@ def __getitem__(self, item):
468456
# code is copied from typing's _GenericAlias and the builtin
469457
# types.GenericAlias.
470458

471-
# A special case in PEP 612 where if X = Callable[P, int],
472-
# then X[int, str] == X[[int, str]].
473-
param_len = len(self.__parameters__)
474-
if param_len == 0:
475-
raise TypeError(f'{self} is not a generic class')
476459
if not isinstance(item, tuple):
477460
item = (item,)
478-
if (param_len == 1 and _is_param_expr(self.__parameters__[0])
461+
# A special case in PEP 612 where if X = Callable[P, int],
462+
# then X[int, str] == X[[int, str]].
463+
if (len(self.__parameters__) == 1
464+
and _is_param_expr(self.__parameters__[0])
479465
and item and not _is_param_expr(item[0])):
480-
item = (list(item),)
481-
item_len = len(item)
482-
if item_len != param_len:
483-
raise TypeError(f'Too {"many" if item_len > param_len else "few"}'
484-
f' arguments for {self};'
485-
f' actual {item_len}, expected {param_len}')
486-
subst = dict(zip(self.__parameters__, item))
487-
new_args = []
488-
for arg in self.__args__:
489-
if _is_typevarlike(arg):
490-
if _is_param_expr(arg):
491-
arg = subst[arg]
492-
if not _is_param_expr(arg):
493-
raise TypeError(f"Expected a list of types, an ellipsis, "
494-
f"ParamSpec, or Concatenate. Got {arg}")
495-
else:
496-
arg = subst[arg]
497-
# Looks like a GenericAlias
498-
elif hasattr(arg, '__parameters__') and isinstance(arg.__parameters__, tuple):
499-
subparams = arg.__parameters__
500-
if subparams:
501-
subargs = tuple(subst[x] for x in subparams)
502-
arg = arg[subargs]
503-
new_args.append(arg)
466+
item = (item,)
467+
468+
new_args = super().__getitem__(item).__args__
504469

505470
# args[0] occurs due to things like Z[[int, str, bool]] from PEP 612
506-
if not isinstance(new_args[0], list):
471+
if not isinstance(new_args[0], (tuple, list)):
507472
t_result = new_args[-1]
508473
t_args = new_args[:-1]
509474
new_args = (t_args, t_result)
510475
return _CallableGenericAlias(Callable, tuple(new_args))
511476

512-
513-
def _is_typevarlike(arg):
514-
obj = type(arg)
515-
# looks like a TypeVar/ParamSpec
516-
return (obj.__module__ == 'typing'
517-
and obj.__name__ in {'ParamSpec', 'TypeVar'})
518-
519477
def _is_param_expr(obj):
520478
"""Checks if obj matches either a list of types, ``...``, ``ParamSpec`` or
521479
``_ConcatenateGenericAlias`` from typing.py
@@ -868,7 +826,7 @@ class KeysView(MappingView, Set):
868826
__slots__ = ()
869827

870828
@classmethod
871-
def _from_iterable(self, it):
829+
def _from_iterable(cls, it):
872830
return set(it)
873831

874832
def __contains__(self, key):
@@ -886,7 +844,7 @@ class ItemsView(MappingView, Set):
886844
__slots__ = ()
887845

888846
@classmethod
889-
def _from_iterable(self, it):
847+
def _from_iterable(cls, it):
890848
return set(it)
891849

892850
def __contains__(self, item):
@@ -1064,10 +1022,10 @@ def index(self, value, start=0, stop=None):
10641022
while stop is None or i < stop:
10651023
try:
10661024
v = self[i]
1067-
if v is value or v == value:
1068-
return i
10691025
except IndexError:
10701026
break
1027+
if v is value or v == value:
1028+
return i
10711029
i += 1
10721030
raise ValueError
10731031

Lib/test/test_collections.py

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -685,14 +685,16 @@ def test_field_descriptor(self):
685685
self.assertRaises(AttributeError, Point.x.__set__, p, 33)
686686
self.assertRaises(AttributeError, Point.x.__delete__, p)
687687

688-
class NewPoint(tuple):
689-
x = pickle.loads(pickle.dumps(Point.x))
690-
y = pickle.loads(pickle.dumps(Point.y))
688+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
689+
with self.subTest(proto=proto):
690+
class NewPoint(tuple):
691+
x = pickle.loads(pickle.dumps(Point.x, proto))
692+
y = pickle.loads(pickle.dumps(Point.y, proto))
691693

692-
np = NewPoint([1, 2])
694+
np = NewPoint([1, 2])
693695

694-
self.assertEqual(np.x, 1)
695-
self.assertEqual(np.y, 2)
696+
self.assertEqual(np.x, 1)
697+
self.assertEqual(np.y, 2)
696698

697699
# TODO: RUSTPYTHON
698700
@unittest.expectedFailure
@@ -706,6 +708,18 @@ def test_match_args(self):
706708
Point = namedtuple('Point', 'x y')
707709
self.assertEqual(Point.__match_args__, ('x', 'y'))
708710

711+
def test_non_generic_subscript(self):
712+
# For backward compatibility, subscription works
713+
# on arbitrary named tuple types.
714+
Group = collections.namedtuple('Group', 'key group')
715+
A = Group[int, list[int]]
716+
self.assertEqual(A.__origin__, Group)
717+
self.assertEqual(A.__parameters__, ())
718+
self.assertEqual(A.__args__, (int, list[int]))
719+
a = A(1, [2])
720+
self.assertIs(type(a), Group)
721+
self.assertEqual(a, (1, [2]))
722+
709723

710724
################################################################################
711725
### Abstract Base Classes
@@ -800,6 +814,8 @@ def throw(self, typ, val=None, tb=None):
800814
def __await__(self):
801815
yield
802816

817+
self.validate_abstract_methods(Awaitable, '__await__')
818+
803819
non_samples = [None, int(), gen(), object()]
804820
for x in non_samples:
805821
self.assertNotIsInstance(x, Awaitable)
@@ -852,6 +868,8 @@ def throw(self, typ, val=None, tb=None):
852868
def __await__(self):
853869
yield
854870

871+
self.validate_abstract_methods(Coroutine, '__await__', 'send', 'throw')
872+
855873
non_samples = [None, int(), gen(), object(), Bar()]
856874
for x in non_samples:
857875
self.assertNotIsInstance(x, Coroutine)
@@ -1597,6 +1615,7 @@ def __len__(self):
15971615
containers = [
15981616
seq,
15991617
ItemsView({1: nan, 2: obj}),
1618+
KeysView({1: nan, 2: obj}),
16001619
ValuesView({1: nan, 2: obj})
16011620
]
16021621
for container in containers:
@@ -1866,6 +1885,8 @@ def test_MutableMapping_subclass(self):
18661885
mymap['red'] = 5
18671886
self.assertIsInstance(mymap.keys(), Set)
18681887
self.assertIsInstance(mymap.keys(), KeysView)
1888+
self.assertIsInstance(mymap.values(), Collection)
1889+
self.assertIsInstance(mymap.values(), ValuesView)
18691890
self.assertIsInstance(mymap.items(), Set)
18701891
self.assertIsInstance(mymap.items(), ItemsView)
18711892

@@ -2381,19 +2402,10 @@ def test_gt(self):
23812402
self.assertFalse(Counter(a=2, b=1, c=0) > Counter('aab'))
23822403

23832404

2384-
################################################################################
2385-
### Run tests
2386-
################################################################################
2387-
2388-
def test_main(verbose=None):
2389-
NamedTupleDocs = doctest.DocTestSuite(module=collections)
2390-
test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
2391-
TestCollectionABCs, TestCounter, TestChainMap,
2392-
TestUserObjects,
2393-
]
2394-
support.run_unittest(*test_classes)
2395-
support.run_doctest(collections, verbose)
2405+
def load_tests(loader, tests, pattern):
2406+
tests.addTest(doctest.DocTestSuite(collections))
2407+
return tests
23962408

23972409

23982410
if __name__ == "__main__":
2399-
test_main(verbose=True)
2411+
unittest.main()

Lib/test/test_typing.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,10 @@ def test_consistency(self):
690690

691691
class CollectionsCallableTests(BaseCallableTests, BaseTestCase):
692692
Callable = collections.abc.Callable
693+
# TODO: RUSTPYTHON
694+
@unittest.expectedFailure
695+
def test_errors(self): # TODO: RUSTPYTHON, remove when this passes
696+
super().test_errors() # TODO: RUSTPYTHON, remove when this passes
693697

694698
# TODO: RUSTPYTHON, AssertionError: 'collections.abc.Callable[__main__.ParamSpec, typing.TypeVar]' != 'collections.abc.Callable[~P, ~T]'
695699
@unittest.expectedFailure
@@ -4916,6 +4920,8 @@ def test_basic_plain(self):
49164920
self.assertEqual(P, P)
49174921
self.assertIsInstance(P, ParamSpec)
49184922

4923+
# TODO: RUSTPYTHON
4924+
@unittest.expectedFailure
49194925
def test_valid_uses(self):
49204926
P = ParamSpec('P')
49214927
T = TypeVar('T')

0 commit comments

Comments
 (0)