Skip to content

Commit

Permalink
Merge branch 'new-typevar-syntax'
Browse files Browse the repository at this point in the history
Closes #539.
  • Loading branch information
JukkaL committed Mar 9, 2015
2 parents 84cdb8a + 233f5bd commit 28a9fcd
Show file tree
Hide file tree
Showing 16 changed files with 94 additions and 89 deletions.
10 changes: 5 additions & 5 deletions docs/source/generics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ as its value. A typical example is a type variable that can only have values
from typing import TypeVar
AnyStr = TypeVar('AnyStr', values=(str, bytes))
AnyStr = TypeVar('AnyStr', str, bytes)
This is actually such a common type variable that ``AnyStr`` is
defined in ``typing`` and we don't need to define it ourselves.
Expand Down Expand Up @@ -209,7 +209,7 @@ this is correct for ``concat``, since ``concat`` actually returns a
>>> print(type(ss))
<class 'str'>
You can also use a ``TypeVar`` with ``values`` when defining a generic
class. For example, mypy uses the type ``typing.Pattern[AnyStr]`` for the
return value of ``re.compile``, since regular expressions can be based
on a string or a bytes pattern.
You can also use a ``TypeVar`` with a restricted set of possible
values when defining a generic class. For example, mypy uses the type
``typing.Pattern[AnyStr]`` for the return value of ``re.compile``,
since regular expressions can be based on a string or a bytes pattern.
2 changes: 1 addition & 1 deletion lib-python/3.2/test/test_random.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

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

RT = TypeVar('RT', values=(random.Random, random.SystemRandom))
RT = TypeVar('RT', random.Random, random.SystemRandom)

class TestBasicOps(unittest.TestCase, Generic[RT]):
# Superclass with tests common to all generators.
Expand Down
2 changes: 1 addition & 1 deletion lib-typing/2.7/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def test_typevar(self):
self.assertIsNone(t.values)

def test_typevar_values(self):
t = TypeVar('t', values=(int, unicode))
t = TypeVar('t', int, unicode)
self.assertEqual(t.name, 't')
self.assertEqual(t.values, (int, unicode))

Expand Down
6 changes: 4 additions & 2 deletions lib-typing/2.7/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,15 @@ def NamedTuple(typename, fields):


class TypeVar(object):
def __init__(self, name, values=None):
def __init__(self, name, *values):
self.name = name
if not values:
values = None
self.values = values


# Predefined type variables.
AnyStr = TypeVar('AnyStr', values=(str, unicode))
AnyStr = TypeVar('AnyStr', str, unicode)


class forwardref(object):
Expand Down
2 changes: 1 addition & 1 deletion lib-typing/3.2/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def test_typevar(self):
self.assertIsNone(t.values)

def test_typevar_values(self):
t = TypeVar('t', values=(int, str))
t = TypeVar('t', int, str)
self.assertEqual(t.name, 't')
self.assertEqual(t.values, (int, str))

Expand Down
6 changes: 4 additions & 2 deletions lib-typing/3.2/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,15 @@ def NamedTuple(typename, fields):


class TypeVar:
def __init__(self, name, *, values=None):
def __init__(self, name, *values):
self.name = name
if not values:
values = None
self.values = values


# Predefined type variables.
AnyStr = TypeVar('AnyStr', values=(str, bytes))
AnyStr = TypeVar('AnyStr', str, bytes)


class forwardref:
Expand Down
29 changes: 12 additions & 17 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -968,11 +968,14 @@ def process_typevar_declaration(self, s: AssignmentStmt) -> None:
if len(call.args) < 1:
self.fail("Too few arguments for TypeVar()", s)
return
if len(call.args) > 2:
self.fail("Too many arguments for TypeVar()", s)
return
if call.arg_kinds not in ([ARG_POS], [ARG_POS, ARG_NAMED]):
self.fail("Unexpected arguments to TypeVar()", s)
if call.arg_kinds != [ARG_POS] * len(call.arg_kinds):
if call.arg_kinds == [ARG_POS, ARG_NAMED] and call.arg_names[1] == 'values':
# Probably using obsolete syntax with values=(...). Explain the current syntax.
self.fail("TypeVar 'values' argument not supported", s)
self.fail("Use TypeVar('T', t, ...) instead of TypeVar('T', values=(t, ...))",
s)
else:
self.fail("Unexpected arguments to TypeVar()", s)
return
if not isinstance(call.args[0], StrExpr):
self.fail("TypeVar() expects a string literal argument", s)
Expand All @@ -988,19 +991,11 @@ def process_typevar_declaration(self, s: AssignmentStmt) -> None:
else:
self.fail("Cannot redefine '%s' as a type variable" % name, s)
return
if len(call.args) == 2:
# Analyze values=(...) argument.
if call.arg_names[1] != 'values':
self.fail("Unexpected keyword argument '{}' to TypeVar()".
format(call.arg_names[1]), s)
return
expr = call.args[1]
if isinstance(expr, TupleExpr):
values = self.analyze_types(expr.items)
else:
self.fail('The values argument must be a tuple literal', s)
return
if len(call.args) > 1:
# Analyze enumeration of type variable values.
values = self.analyze_types(call.args[1:])
else:
# Type variables can refer to an arbitrary type.
values = []
# Yes, it's a valid type variable definition! Add it to the symbol table.
node = self.lookup(name, s)
Expand Down
2 changes: 1 addition & 1 deletion mypy/test/data/check-generics.test
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ a = '' # E: Incompatible types in assignment (expression has type "str", variabl

[case testSubtypingWithGenericFunctionUsingTypevarWithValues]
from typing import TypeVar, Callable
T = TypeVar('T', values=(int, str))
T = TypeVar('T', int, str)
def f(x: T) -> T: pass
def g1(f: Callable[[str], str]) -> None: pass
g1(f)
Expand Down
Loading

0 comments on commit 28a9fcd

Please sign in to comment.