Skip to content

Commit

Permalink
gh-102721: Improve coverage of `_collections_abc._CallableGenericAlia…
Browse files Browse the repository at this point in the history
…s` (#102722)

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
  • Loading branch information
sobolevn and AlexWaygood committed Mar 16, 2023
1 parent b0ec625 commit fbe82fd
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 14 deletions.
7 changes: 0 additions & 7 deletions Lib/_collections_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,15 +481,8 @@ def __getitem__(self, item):
# rather than the default types.GenericAlias object. Most of the
# code is copied from typing's _GenericAlias and the builtin
# types.GenericAlias.

if not isinstance(item, tuple):
item = (item,)
# A special case in PEP 612 where if X = Callable[P, int],
# then X[int, str] == X[[int, str]].
if (len(self.__parameters__) == 1
and _is_param_expr(self.__parameters__[0])
and item and not _is_param_expr(item[0])):
item = (item,)

new_args = super().__getitem__(item).__args__

Expand Down
39 changes: 32 additions & 7 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1921,14 +1921,29 @@ def test_weakref(self):
self.assertEqual(weakref.ref(alias)(), alias)

def test_pickle(self):
global T_pickle, P_pickle, TS_pickle # needed for pickling
Callable = self.Callable
alias = Callable[[int, str], float]
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
s = pickle.dumps(alias, proto)
loaded = pickle.loads(s)
self.assertEqual(alias.__origin__, loaded.__origin__)
self.assertEqual(alias.__args__, loaded.__args__)
self.assertEqual(alias.__parameters__, loaded.__parameters__)
T_pickle = TypeVar('T_pickle')
P_pickle = ParamSpec('P_pickle')
TS_pickle = TypeVarTuple('TS_pickle')

samples = [
Callable[[int, str], float],
Callable[P_pickle, int],
Callable[P_pickle, T_pickle],
Callable[Concatenate[int, P_pickle], int],
Callable[Concatenate[*TS_pickle, P_pickle], int],
]
for alias in samples:
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.subTest(alias=alias, proto=proto):
s = pickle.dumps(alias, proto)
loaded = pickle.loads(s)
self.assertEqual(alias.__origin__, loaded.__origin__)
self.assertEqual(alias.__args__, loaded.__args__)
self.assertEqual(alias.__parameters__, loaded.__parameters__)

del T_pickle, P_pickle, TS_pickle # cleaning up global state

def test_var_substitution(self):
Callable = self.Callable
Expand All @@ -1954,6 +1969,16 @@ def test_var_substitution(self):
self.assertEqual(C5[int, str, float],
Callable[[typing.List[int], tuple[str, int], float], int])

def test_type_subst_error(self):
Callable = self.Callable
P = ParamSpec('P')
T = TypeVar('T')

pat = "Expected a list of types, an ellipsis, ParamSpec, or Concatenate."

with self.assertRaisesRegex(TypeError, pat):
Callable[P, T][0, int]

def test_type_erasure(self):
Callable = self.Callable
class C1(Callable):
Expand Down

0 comments on commit fbe82fd

Please sign in to comment.