Skip to content

Commit

Permalink
stubtest: check typevar and paramspec (#12851)
Browse files Browse the repository at this point in the history
Came up in #12825
  • Loading branch information
hauntsaninja committed May 26, 2022
1 parent 4024748 commit b55dcf5
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 4 deletions.
30 changes: 28 additions & 2 deletions mypy/stubtest.py
Expand Up @@ -12,6 +12,8 @@
import re
import sys
import types
import typing
import typing_extensions
import warnings
from functools import singledispatch
from pathlib import Path
Expand Down Expand Up @@ -867,8 +869,32 @@ def verify_overloadedfuncdef(
def verify_typevarexpr(
stub: nodes.TypeVarExpr, runtime: MaybeMissing[Any], object_path: List[str]
) -> Iterator[Error]:
if False:
yield None
if isinstance(runtime, Missing):
# We seem to insert these typevars into NamedTuple stubs, but they
# don't exist at runtime. Just ignore!
if stub.name == "_NT":
return
yield Error(object_path, "is not present at runtime", stub, runtime)
return
if not isinstance(runtime, TypeVar):
yield Error(object_path, "is not a TypeVar", stub, runtime)
return


@verify.register(nodes.ParamSpecExpr)
def verify_paramspecexpr(
stub: nodes.ParamSpecExpr, runtime: MaybeMissing[Any], object_path: List[str]
) -> Iterator[Error]:
if isinstance(runtime, Missing):
yield Error(object_path, "is not present at runtime", stub, runtime)
return
maybe_paramspec_types = (
getattr(typing, "ParamSpec", None), getattr(typing_extensions, "ParamSpec", None)
)
paramspec_types = tuple([t for t in maybe_paramspec_types if t is not None])
if not paramspec_types or not isinstance(runtime, paramspec_types):
yield Error(object_path, "is not a ParamSpec", stub, runtime)
return


def _verify_readonly_property(stub: nodes.Decorator, runtime: Any) -> Iterator[str]:
Expand Down
34 changes: 32 additions & 2 deletions mypy/test/teststubtest.py
Expand Up @@ -48,6 +48,9 @@ def __getitem__(self, typeargs: Any) -> object: ...
class TypeVar:
def __init__(self, name, covariant: bool = ..., contravariant: bool = ...) -> None: ...
class ParamSpec:
def __init__(self, name: str) -> None: ...
_T = TypeVar("_T")
_T_co = TypeVar("_T_co", covariant=True)
_K = TypeVar("_K")
Expand Down Expand Up @@ -329,8 +332,8 @@ def test_default_value(self) -> Iterator[Case]:
yield Case(
stub="""
from typing import TypeVar
T = TypeVar("T", bound=str)
def f6(text: T = ...) -> None: ...
_T = TypeVar("_T", bound=str)
def f6(text: _T = ...) -> None: ...
""",
runtime="def f6(text = None): pass",
error="f6",
Expand Down Expand Up @@ -1042,6 +1045,33 @@ def foo(self, x: int, y: bytes = ...) -> str: ...
error="X.__init__"
)

@collect_cases
def test_type_var(self) -> Iterator[Case]:
yield Case(
stub="from typing import TypeVar", runtime="from typing import TypeVar", error=None
)
yield Case(
stub="A = TypeVar('A')",
runtime="A = TypeVar('A')",
error=None,
)
yield Case(
stub="B = TypeVar('B')",
runtime="B = 5",
error="B",
)
if sys.version_info >= (3, 10):
yield Case(
stub="from typing import ParamSpec",
runtime="from typing import ParamSpec",
error=None
)
yield Case(
stub="C = ParamSpec('C')",
runtime="C = ParamSpec('C')",
error=None,
)


def remove_color_code(s: str) -> str:
return re.sub("\\x1b.*?m", "", s) # this works!
Expand Down

0 comments on commit b55dcf5

Please sign in to comment.