Skip to content

Commit

Permalink
add test type hints
Browse files Browse the repository at this point in the history
  • Loading branch information
gaborbernat committed Jun 8, 2018
1 parent ea57a03 commit c4ed8c8
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 76 deletions.
4 changes: 3 additions & 1 deletion mypy/stub_src_merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,9 @@ def decorator_argument_checks(self, src: CallExpr, stub: CallExpr) -> None:
for name, default_node in zip(stub.arg_names, stub.args):
self.check_no_explicit_default(default_node, src, name)

def check_no_explicit_default(self, default_node, node, name):
def check_no_explicit_default(
self, default_node: Node, node: Node, name: str
) -> None:
"""check that no default value is set for this node"""
if not isinstance(node, TempNode) and not isinstance(
default_node, EllipsisExpr
Expand Down
129 changes: 54 additions & 75 deletions mypy/test/test_stub_src_merge.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import re
import textwrap
from typing import Any, List, Optional, Pattern, Tuple, cast
from typing import Callable, Generator, List, Optional, Pattern, Tuple, cast

import pytest
from _pytest.capture import CaptureFixture
Expand All @@ -12,6 +12,8 @@
from mypy.errors import Errors
from mypy.options import Options

Checker = Callable[[str, str, Optional[str]], None]


@pytest.fixture(name="checker_resource", scope="session")
def checker_resource_fixture() -> Tuple[Pattern, Options]:
Expand All @@ -30,12 +32,10 @@ def checker_resource_fixture() -> Tuple[Pattern, Options]:
@pytest.fixture(name="checker")
def checker_fixture(
checker_resource: Tuple[Pattern, Options], tmpdir: LocalPath, capsys: CaptureFixture
) -> Any:
) -> Generator[Checker, None, None]:
line_nr, options = checker_resource

def _do(
src: str, stub: str, result: Optional[str] = None
) -> Tuple[List[Errors], List[Errors]]:
def _do(src: str, stub: str, result: Optional[str] = None) -> List[Errors]:
src_path = str(tmpdir.join("t.py"))
stub_path = str(tmpdir.join("t.pyi"))
files = {src_path: src, stub_path: stub}
Expand All @@ -59,7 +59,7 @@ def _do(
assert result_ast == combined_ast
capsys.readouterr()
errors = combined_res.manager.errors.error_info_map
return errors.get(src_path, []), errors.get(stub_path, [])
return errors.get(src_path, [])

def _build_ast(source):
path = source.merge_with.path if source.merge_with is not None else source.path
Expand All @@ -73,8 +73,8 @@ def _build_ast(source):
yield _do


def test_stub_src_type_does_not_match(checker):
src_errors, stub_errors = checker(
def test_stub_src_type_does_not_match(checker: Checker) -> None:
src_errors = checker(
"""
a = 1""",
"""
Expand All @@ -83,11 +83,10 @@ def a() -> None: ...""",
assert [i.message for i in src_errors] == [
"conflict of src Var and stub:2 FuncDef definition"
]
assert not stub_errors


def test_merge_module_func_arg_conflict(checker):
src_errors, stub_errors = checker(
def test_merge_module_func_arg_conflict(checker: Checker) -> None:
src_errors = checker(
"""
def a(arg): ...""",
"""
Expand All @@ -96,11 +95,10 @@ def a(arg1) -> None: ...""",
assert [i.message for i in src_errors] == [
"arg conflict of src ['arg'] and stub (line 2) ['arg1']"
]
assert not stub_errors


def test_merge_module_func(checker):
src_errors, stub_errors = checker(
def test_merge_module_func(checker: Checker) -> None:
src_errors = checker(
"""
def fancy_add(a, b = None):
pass""",
Expand All @@ -113,11 +111,10 @@ def fancy_add(a : int, b : Union[None, int] = None) -> int:
pass""",
)
assert not src_errors
assert not stub_errors


def test_module_variable(checker):
src_errors, stub_errors = checker(
def test_module_variable(checker: Checker) -> None:
src_errors = checker(
"""VERSION = ('1', '2', 3)""",
"""
from typing import Tuple
Expand All @@ -127,11 +124,10 @@ def test_module_variable(checker):
VERSION : Tuple[str, str, int] = ('1', '2', 3)""",
)
assert not src_errors
assert not stub_errors


def test_class_variable_default(checker):
src_errors, stub_errors = checker(
def test_class_variable_default(checker: Checker) -> None:
src_errors = checker(
"""
class A:
b = 1""",
Expand All @@ -143,11 +139,10 @@ class A:
b : int = 1""",
)
assert not src_errors
assert not stub_errors


def test_class_init_self_can_be_defined_at_class_level(checker):
src_errors, stub_errors = checker(
def test_class_init_self_can_be_defined_at_class_level(checker: Checker) -> None:
src_errors = checker(
"""
class A:
def __init__(self):
Expand All @@ -162,11 +157,10 @@ def __init__(self) -> None:
self.a : str = 's'""",
)
assert not src_errors
assert not stub_errors


def test_class_init_not_defined(checker):
src_errors, stub_errors = checker(
def test_class_init_not_defined(checker: Checker) -> None:
src_errors = checker(
"""
class A:
def __init__(self):
Expand All @@ -177,11 +171,12 @@ class A:
def __init__(self) -> None: ...""",
)
assert [i.message for i in src_errors] == ["no stub definition for class member a"]
assert not stub_errors


def test_class_init_self_can_be_defined_at_class_level_inside_if(checker):
src_errors, stub_errors = checker(
def test_class_init_self_can_be_defined_at_class_level_inside_if(
checker: Checker
) -> None:
src_errors = checker(
"""
class A:
def __init__(self):
Expand All @@ -202,11 +197,10 @@ def __init__(self) -> None:
self.a = 1""",
)
assert not src_errors
assert not stub_errors


def test_class_decorator(checker):
src_errors, stub_errors = checker(
def test_class_decorator(checker: Checker) -> None:
src_errors = checker(
"""
class A:
@classmethod
Expand All @@ -223,11 +217,10 @@ def a(cls) -> None:
pass""",
)
assert not src_errors
assert not stub_errors


def test_variable_module_level(checker):
src_errors, stub_errors = checker(
def test_variable_module_level(checker: Checker) -> None:
src_errors = checker(
"""
a = 1""",
"""
Expand All @@ -236,11 +229,10 @@ def test_variable_module_level(checker):
a : int = 1""",
)
assert not src_errors
assert not stub_errors


def test_decorator_func(checker):
src_errors, stub_errors = checker(
def test_decorator_func(checker: Checker) -> None:
src_errors = checker(
"""
@d(p=1, r=2)
def a():
Expand All @@ -254,11 +246,10 @@ def a() -> None:
pass""",
)
assert not src_errors
assert not stub_errors


def test_decorator_func_args_not_ellipse(checker):
src_errors, stub_errors = checker(
def test_decorator_func_args_not_ellipse(checker: Checker) -> None:
src_errors = checker(
"""
@d(p=1, r=None)
def a():
Expand All @@ -271,11 +262,10 @@ def a() -> None: ...""",
"stub should not contain default value, p has IntExpr",
"stub should not contain default value, r has NameExpr",
]
assert not stub_errors


def test_decorator_func_args_keys_differ(checker):
src_errors, stub_errors = checker(
def test_decorator_func_args_keys_differ(checker: Checker) -> None:
src_errors = checker(
"""
@d(p=1, v=None)
def a():
Expand All @@ -287,11 +277,10 @@ def a() -> None: ...""",
assert [i.message for i in src_errors] == [
"conflict of src v and stub r decorator argument name"
]
assert not stub_errors


def test_decorator_func_call_expr_name_differ(checker):
src_errors, stub_errors = checker(
def test_decorator_func_call_expr_name_differ(checker: Checker) -> None:
src_errors = checker(
"""
@de(p=1)
def a():
Expand All @@ -303,11 +292,10 @@ def a() -> None: ...""",
assert [i.message for i in src_errors] == [
"conflict of src de and stub d decorator name"
]
assert not stub_errors


def test_decorator_name_does_not_match(checker):
src_errors, stub_errors = checker(
def test_decorator_name_does_not_match(checker: Checker) -> None:
src_errors = checker(
"""
@d
def a(): pass""",
Expand All @@ -318,11 +306,10 @@ def a() -> None: ...""",
assert [i.message for i in src_errors] == [
"conflict of src d and stub de decorator name"
]
assert not stub_errors


def test_decorator_source_less(checker):
src_errors, stub_errors = checker(
def test_decorator_source_less(checker: Checker) -> None:
src_errors = checker(
"""
@d
def a(): pass""",
Expand All @@ -334,11 +321,10 @@ def a() -> None: ...""",
assert [i.message for i in src_errors] == [
"conflict of src NoneType and stub NameExpr decorator"
]
assert not stub_errors


def test_decorator_stub_less(checker):
src_errors, stub_errors = checker(
def test_decorator_stub_less(checker: Checker) -> None:
src_errors = checker(
"""
@d
@de
Expand All @@ -350,11 +336,10 @@ def a() -> None: ...""",
assert [i.message for i in src_errors] == [
"conflict of src NameExpr and stub NoneType decorator"
]
assert not stub_errors


def test_decorator_expr_does_not_match(checker):
src_errors, stub_errors = checker(
def test_decorator_expr_does_not_match(checker: Checker) -> None:
src_errors = checker(
"""
@d(p=1)
def a(): pass""",
Expand All @@ -365,11 +350,10 @@ def a() -> None: ...""",
assert [i.message for i in src_errors] == [
"conflict of src p and stub pe decorator argument name"
]
assert not stub_errors


def test_decorator_expr_stub_not_ellipsis(checker):
src_errors, stub_errors = checker(
def test_decorator_expr_stub_not_ellipsis(checker: Checker) -> None:
src_errors = checker(
"""
@d(p=1)
def a(): pass""",
Expand All @@ -380,11 +364,10 @@ def a() -> None: ...""",
assert [i.message for i in src_errors] == [
"stub should not contain default value, p has IntExpr"
]
assert not stub_errors


def test_class_decorator_no_source_decorator(checker):
src_errors, stub_errors = checker(
def test_class_decorator_no_source_decorator(checker: Checker) -> None:
src_errors = checker(
"""
class A:
pass""",
Expand All @@ -394,11 +377,10 @@ class A:
def a(cls) -> None: ...""",
)
assert [i.message for i in src_errors] == ["no source for func a @stub:3"]
assert not stub_errors


def test_class_decorator_no_source_func(checker):
src_errors, stub_errors = checker(
def test_class_decorator_no_source_func(checker: Checker) -> None:
src_errors = checker(
"""
class A:
pass""",
Expand All @@ -407,11 +389,10 @@ class A:
def a(cls) -> None: ...""",
)
assert [i.message for i in src_errors] == ["no source for func a @stub:3"]
assert not stub_errors


def test_class_decorator_no_source_assignment(checker):
src_errors, stub_errors = checker(
def test_class_decorator_no_source_assignment(checker: Checker) -> None:
src_errors = checker(
"""
class A:
pass""",
Expand All @@ -420,12 +401,11 @@ class A:
a : int = ...""",
)
assert [i.message for i in src_errors] == ["no source for assign a @stub:3"]
assert not stub_errors


def test_module_variable_complex_not_supported(checker):
def test_module_variable_complex_not_supported(checker: Checker) -> None:
# TODO: should we warn for stub only?
src_errors, stub_errors = checker(
src_errors = checker(
"""
class A:
a, b = 1, 2""",
Expand All @@ -437,4 +417,3 @@ class A:
"l-values must be simple name expressions, is TupleExpr", # src
"l-values must be simple name expressions, is TupleExpr", # stub
]
assert not stub_errors

0 comments on commit c4ed8c8

Please sign in to comment.