Skip to content

Commit

Permalink
Discard the default arg of TypeVar
Browse files Browse the repository at this point in the history
It is not implemented yet, but this allows us to still be able to parse latest typeshed.

This is a Python 3.13 feature.

PiperOrigin-RevId: 702318253
  • Loading branch information
oprypin authored and copybara-github committed Dec 3, 2024
1 parent 8992c80 commit 720d393
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
16 changes: 14 additions & 2 deletions pytype/overlays/typing_overlay.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,16 @@ def _get_typeparam_args(self, node, args):
contravariant = self._get_namedarg(node, args, "contravariant", False)
if constraints and bound:
raise TypeVarError("constraints and a bound are mutually exclusive")
extra_kwargs = set(args.namedargs) - {"bound", "covariant", "contravariant"}
# `default` is unsupported for now - access it just to generate a warning.
# TODO: b/382028836 - actually support the `default` arg to `TypeVar`
self._get_namedarg(node, args, "default", None)

extra_kwargs = set(args.namedargs) - {
"bound",
"covariant",
"contravariant",
"default",
}
if extra_kwargs:
raise TypeVarError("extra keyword arguments: " + ", ".join(extra_kwargs))
if args.starargs:
Expand Down Expand Up @@ -345,7 +354,10 @@ def _get_namedarg(self, node, args, name, default_value):
if name == "bound":
return self._get_annotation(node, args.namedargs[name], name)
else:
ret = self._get_constant(args.namedargs[name], name, bool)
if name == "default":
ret = self._get_annotation(node, args.namedargs[name], name)
else:
ret = self._get_constant(args.namedargs[name], name, bool)
# This error is logged only if _get_constant succeeds.
self.ctx.errorlog.not_supported_yet(
self.ctx.vm.frames, f'argument "{name}" to TypeVar'
Expand Down
10 changes: 8 additions & 2 deletions pytype/stubs/builtins/typing.pytd
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,14 @@ Text = str
# purposes and to make it easier for pytype to type-check arguments to TypeVar
# and ParamSpec.
def _typevar_new(
name: str, *constraints: type | str | None, bound: type | str | None = None,
covariant: bool = False, contravariant: bool = False): ...
name: str,
*constraints: type | str | None,
bound: type | str | None = None,
covariant: bool = False,
contravariant: bool = False,
infer_variance: bool = False,
default: Any = None,
): ...
def _paramspec_new(
name: str, *constraints: type | str | None, bound: type | str | None = None,
covariant: bool = False, contravariant: bool = False): ...
Expand Down
35 changes: 35 additions & 0 deletions pytype/tests/test_typevar1.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,41 @@ def test_contravariant(self):
},
)

def test_default(self):
ty = self.Infer("""
from typing import Generic, TypeVar
T = TypeVar("T", default=int) # pytype: disable=not-supported-yet
class Foo(Generic[T]):
pass
f = Foo()
""")
self.assertTypesMatchPytd(
ty,
"""
from typing import Generic, TypeVar
T = TypeVar('T')
class Foo(Generic[T]): ...
f: Foo[nothing]
""",
)

self.CheckWithErrors("""
from typing import Generic, TypeVar
T = TypeVar("T", default=int) # not-supported-yet
class Foo(Generic[T]):
pass
f = Foo()
""")

def test_dont_propagate_pyval(self):
# in functions like f(x: T) -> T, if T has constraints we should not copy
# the value of constant types between instances of the typevar.
Expand Down

0 comments on commit 720d393

Please sign in to comment.