Prohibit Callable[[...], X] (#320)
diff --git a/python2/test_typing.py b/python2/test_typing.py
index 5de042a..1b4377e 100644
--- a/python2/test_typing.py
+++ b/python2/test_typing.py
@@ -375,6 +375,14 @@
with self.assertRaises(TypeError):
type(c)()
+ def test_callable_wrong_forms(self):
+ with self.assertRaises(TypeError):
+ Callable[(), int]
+ with self.assertRaises(TypeError):
+ Callable[[()], int]
+ with self.assertRaises(TypeError):
+ Callable[[int, 1], 2]
+
def test_callable_instance_works(self):
def f():
pass
diff --git a/python2/typing.py b/python2/typing.py
index 5df0062..3242be8 100644
--- a/python2/typing.py
+++ b/python2/typing.py
@@ -1281,14 +1281,12 @@
# super(CallableMeta, self)._tree_repr() for nice formatting.
arg_list = []
for arg in tree[1:]:
- if arg == ():
- arg_list.append('[]')
- elif not isinstance(arg, tuple):
+ if not isinstance(arg, tuple):
arg_list.append(_type_repr(arg))
else:
arg_list.append(arg[0]._tree_repr(arg))
- if len(arg_list) == 2:
- return repr(tree[0]) + '[%s]' % ', '.join(arg_list)
+ if arg_list[0] == '...':
+ return repr(tree[0]) + '[..., %s]' % arg_list[1]
return (repr(tree[0]) +
'[[%s], %s]' % (', '.join(arg_list[:-1]), arg_list[-1]))
@@ -1305,25 +1303,20 @@
args, result = parameters
if args is Ellipsis:
parameters = (Ellipsis, result)
- elif args == []:
- parameters = ((), result)
else:
if not isinstance(args, list):
raise TypeError("Callable[args, result]: args must be a list."
" Got %.100r." % (args,))
- parameters = tuple(args) + (result,)
+ parameters = (tuple(args), result)
return self.__getitem_inner__(parameters)
@_tp_cache
def __getitem_inner__(self, parameters):
- args = parameters[:-1]
- result = parameters[-1]
+ args, result = parameters
msg = "Callable[args, result]: result must be a type."
result = _type_check(result, msg)
- if args == (Ellipsis,):
+ if args is Ellipsis:
return super(CallableMeta, self).__getitem__((_TypingEllipsis, result))
- if args == ((),):
- return super(CallableMeta, self).__getitem__((_TypingEmpty, result))
msg = "Callable[[arg, ...], result]: each arg must be a type."
args = tuple(_type_check(arg, msg) for arg in args)
parameters = args + (result,)
diff --git a/src/test_typing.py b/src/test_typing.py
index d9a8eb8..ae9de61 100644
--- a/src/test_typing.py
+++ b/src/test_typing.py
@@ -378,6 +378,16 @@
with self.assertRaises(TypeError):
type(c)()
+ def test_callable_wrong_forms(self):
+ with self.assertRaises(TypeError):
+ Callable[[...], int]
+ with self.assertRaises(TypeError):
+ Callable[(), int]
+ with self.assertRaises(TypeError):
+ Callable[[()], int]
+ with self.assertRaises(TypeError):
+ Callable[[int, 1], 2]
+
def test_callable_instance_works(self):
def f():
pass
diff --git a/src/typing.py b/src/typing.py
index 161254a..e748fd9 100644
--- a/src/typing.py
+++ b/src/typing.py
@@ -1192,14 +1192,12 @@
# super()._tree_repr() for nice formatting.
arg_list = []
for arg in tree[1:]:
- if arg == ():
- arg_list.append('[]')
- elif not isinstance(arg, tuple):
+ if not isinstance(arg, tuple):
arg_list.append(_type_repr(arg))
else:
arg_list.append(arg[0]._tree_repr(arg))
- if len(arg_list) == 2:
- return repr(tree[0]) + '[%s]' % ', '.join(arg_list)
+ if arg_list[0] == '...':
+ return repr(tree[0]) + '[..., %s]' % arg_list[1]
return (repr(tree[0]) +
'[[%s], %s]' % (', '.join(arg_list[:-1]), arg_list[-1]))
@@ -1214,26 +1212,22 @@
raise TypeError("Callable must be used as "
"Callable[[arg, ...], result].")
args, result = parameters
- if args is ...:
- parameters = (..., result)
- elif args == []:
- parameters = ((), result)
+ if args is Ellipsis:
+ parameters = (Ellipsis, result)
else:
if not isinstance(args, list):
raise TypeError("Callable[args, result]: args must be a list."
" Got %.100r." % (args,))
- parameters = tuple(args) + (result,)
+ parameters = (tuple(args), result)
return self.__getitem_inner__(parameters)
@_tp_cache
def __getitem_inner__(self, parameters):
- *args, result = parameters
+ args, result = parameters
msg = "Callable[args, result]: result must be a type."
result = _type_check(result, msg)
- if args == [...,]:
+ if args is Ellipsis:
return super().__getitem__((_TypingEllipsis, result))
- if args == [(),]:
- return super().__getitem__((_TypingEmpty, result))
msg = "Callable[[arg, ...], result]: each arg must be a type."
args = tuple(_type_check(arg, msg) for arg in args)
parameters = args + (result,)