Skip to content

Commit 28a9fcd

Browse files
committed
Merge branch 'new-typevar-syntax'
Closes #539.
2 parents 84cdb8a + 233f5bd commit 28a9fcd

16 files changed

+94
-89
lines changed

docs/source/generics.rst

+5-5
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ as its value. A typical example is a type variable that can only have values
151151
152152
from typing import TypeVar
153153
154-
AnyStr = TypeVar('AnyStr', values=(str, bytes))
154+
AnyStr = TypeVar('AnyStr', str, bytes)
155155
156156
This is actually such a common type variable that ``AnyStr`` is
157157
defined in ``typing`` and we don't need to define it ourselves.
@@ -209,7 +209,7 @@ this is correct for ``concat``, since ``concat`` actually returns a
209209
>>> print(type(ss))
210210
<class 'str'>
211211
212-
You can also use a ``TypeVar`` with ``values`` when defining a generic
213-
class. For example, mypy uses the type ``typing.Pattern[AnyStr]`` for the
214-
return value of ``re.compile``, since regular expressions can be based
215-
on a string or a bytes pattern.
212+
You can also use a ``TypeVar`` with a restricted set of possible
213+
values when defining a generic class. For example, mypy uses the type
214+
``typing.Pattern[AnyStr]`` for the return value of ``re.compile``,
215+
since regular expressions can be based on a string or a bytes pattern.

lib-python/3.2/test/test_random.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from typing import Undefined, Any, Dict, List, Callable, Generic, TypeVar
1212

13-
RT = TypeVar('RT', values=(random.Random, random.SystemRandom))
13+
RT = TypeVar('RT', random.Random, random.SystemRandom)
1414

1515
class TestBasicOps(unittest.TestCase, Generic[RT]):
1616
# Superclass with tests common to all generators.

lib-typing/2.7/test_typing.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def test_typevar(self):
7373
self.assertIsNone(t.values)
7474

7575
def test_typevar_values(self):
76-
t = TypeVar('t', values=(int, unicode))
76+
t = TypeVar('t', int, unicode)
7777
self.assertEqual(t.name, 't')
7878
self.assertEqual(t.values, (int, unicode))
7979

lib-typing/2.7/typing.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,15 @@ def NamedTuple(typename, fields):
183183

184184

185185
class TypeVar(object):
186-
def __init__(self, name, values=None):
186+
def __init__(self, name, *values):
187187
self.name = name
188+
if not values:
189+
values = None
188190
self.values = values
189191

190192

191193
# Predefined type variables.
192-
AnyStr = TypeVar('AnyStr', values=(str, unicode))
194+
AnyStr = TypeVar('AnyStr', str, unicode)
193195

194196

195197
class forwardref(object):

lib-typing/3.2/test_typing.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def test_typevar(self):
7171
self.assertIsNone(t.values)
7272

7373
def test_typevar_values(self):
74-
t = TypeVar('t', values=(int, str))
74+
t = TypeVar('t', int, str)
7575
self.assertEqual(t.name, 't')
7676
self.assertEqual(t.values, (int, str))
7777

lib-typing/3.2/typing.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,15 @@ def NamedTuple(typename, fields):
183183

184184

185185
class TypeVar:
186-
def __init__(self, name, *, values=None):
186+
def __init__(self, name, *values):
187187
self.name = name
188+
if not values:
189+
values = None
188190
self.values = values
189191

190192

191193
# Predefined type variables.
192-
AnyStr = TypeVar('AnyStr', values=(str, bytes))
194+
AnyStr = TypeVar('AnyStr', str, bytes)
193195

194196

195197
class forwardref:

mypy/semanal.py

+12-17
Original file line numberDiff line numberDiff line change
@@ -968,11 +968,14 @@ def process_typevar_declaration(self, s: AssignmentStmt) -> None:
968968
if len(call.args) < 1:
969969
self.fail("Too few arguments for TypeVar()", s)
970970
return
971-
if len(call.args) > 2:
972-
self.fail("Too many arguments for TypeVar()", s)
973-
return
974-
if call.arg_kinds not in ([ARG_POS], [ARG_POS, ARG_NAMED]):
975-
self.fail("Unexpected arguments to TypeVar()", s)
971+
if call.arg_kinds != [ARG_POS] * len(call.arg_kinds):
972+
if call.arg_kinds == [ARG_POS, ARG_NAMED] and call.arg_names[1] == 'values':
973+
# Probably using obsolete syntax with values=(...). Explain the current syntax.
974+
self.fail("TypeVar 'values' argument not supported", s)
975+
self.fail("Use TypeVar('T', t, ...) instead of TypeVar('T', values=(t, ...))",
976+
s)
977+
else:
978+
self.fail("Unexpected arguments to TypeVar()", s)
976979
return
977980
if not isinstance(call.args[0], StrExpr):
978981
self.fail("TypeVar() expects a string literal argument", s)
@@ -988,19 +991,11 @@ def process_typevar_declaration(self, s: AssignmentStmt) -> None:
988991
else:
989992
self.fail("Cannot redefine '%s' as a type variable" % name, s)
990993
return
991-
if len(call.args) == 2:
992-
# Analyze values=(...) argument.
993-
if call.arg_names[1] != 'values':
994-
self.fail("Unexpected keyword argument '{}' to TypeVar()".
995-
format(call.arg_names[1]), s)
996-
return
997-
expr = call.args[1]
998-
if isinstance(expr, TupleExpr):
999-
values = self.analyze_types(expr.items)
1000-
else:
1001-
self.fail('The values argument must be a tuple literal', s)
1002-
return
994+
if len(call.args) > 1:
995+
# Analyze enumeration of type variable values.
996+
values = self.analyze_types(call.args[1:])
1003997
else:
998+
# Type variables can refer to an arbitrary type.
1004999
values = []
10051000
# Yes, it's a valid type variable definition! Add it to the symbol table.
10061001
node = self.lookup(name, s)

mypy/test/data/check-generics.test

+1-1
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ a = '' # E: Incompatible types in assignment (expression has type "str", variabl
793793

794794
[case testSubtypingWithGenericFunctionUsingTypevarWithValues]
795795
from typing import TypeVar, Callable
796-
T = TypeVar('T', values=(int, str))
796+
T = TypeVar('T', int, str)
797797
def f(x: T) -> T: pass
798798
def g1(f: Callable[[str], str]) -> None: pass
799799
g1(f)

0 commit comments

Comments
 (0)