Skip to content

Commit 731e39c

Browse files
authored
Merge pull request #19 from George-Ogden/builtin-iter
Ignore Standard Library `[iterable-sequence]` warnings
2 parents afc2ce4 + 49a31c5 commit 731e39c

File tree

7 files changed

+50
-7
lines changed

7 files changed

+50
-7
lines changed

mypy_pytest_plugin/iterable_sequence_checker.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from collections.abc import Collection, Sequence
22
from dataclasses import dataclass
3+
import sys
34

45
from mypy.argmap import map_formals_to_actuals
56
from mypy.checker import TypeChecker
@@ -16,16 +17,33 @@ class IterableSequenceChecker:
1617
checker: TypeChecker
1718

1819
def check_iterable_sequence_call(self, call: CallExpr) -> None:
20+
if not self.is_builtin_function(call.callee):
21+
self.check_iterable_sequence_arguments(call)
22+
23+
def is_builtin_function(self, expression: Expression) -> bool:
24+
expression_type = self.checker.lookup_type(expression)
25+
if (
26+
isinstance(expression_type, CallableType)
27+
and (def_ := expression_type.definition) is not None
28+
):
29+
[module, *_] = def_.fullname.split(".", maxsplit=1) if def_ else [""]
30+
return module in sys.stdlib_module_names
31+
return False
32+
33+
def check_iterable_sequence_arguments(self, call: CallExpr) -> None:
1934
for argument, expected_type in self.actuals_formals_mapping_bijective_subset(call):
20-
argument_type = self.checker.lookup_type(argument)
21-
if self.is_sequence(argument_type) and self.is_iterable(expected_type):
22-
self._display_error_message(expected_type, argument_type, argument)
35+
self.check_iterable_sequence_argument(argument, expected_type)
36+
37+
def check_iterable_sequence_argument(self, argument: Expression, expected_type: Type) -> None:
38+
argument_type = self.checker.lookup_type(argument)
39+
if self.is_sequence(argument_type) and self.is_iterable(expected_type):
40+
self._display_error_message(expected_type, argument_type, argument)
2341

2442
def _display_error_message(
2543
self, expected_type: Type, argument_type: Type, context: Context
2644
) -> None:
2745
self.checker.fail(
28-
f"Expected {format_type(expected_type, self.checker.options)}, got {format_type(argument_type, self.checker.options)}.",
46+
f"Argument has type {format_type(argument_type, self.checker.options)}; expected {format_type(expected_type, self.checker.options)}.",
2947
context,
3048
code=ITERABLE_SEQUENCE,
3149
)

mypy_pytest_plugin/iterable_sequence_checker_test.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,21 @@ def foo(cls, it: Iterable) -> int:
169169
""",
170170
errors=["iterable-sequence"],
171171
)
172+
173+
174+
def test_check_iterable_sequence_builtin() -> None:
175+
_check_iterable_sequence_call_test_body(
176+
"""
177+
call = tuple([1, 2, 3])
178+
"""
179+
)
180+
181+
182+
def test_check_iterable_sequence_stdlib() -> None:
183+
_check_iterable_sequence_call_test_body(
184+
"""
185+
import itertools
186+
187+
call = itertools.pairwise([1, 2, 3])
188+
"""
189+
)

mypy_pytest_plugin/plugin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def __init__(self, options: Options) -> None:
3131
options.per_module_options.setdefault(module_pattern, {})["ignore_missing_imports"] = (
3232
True
3333
)
34+
options.preserve_asts = True
3435
super().__init__(options)
3536

3637
def get_additional_deps(self, file: MypyFile) -> list[tuple[int, str, int]]:

mypy_pytest_plugin/test_info_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,7 @@ def test_info(bool_fixture: Literal[True]) -> None:
841841
)
842842

843843

844+
@pytest.mark.local_only
844845
def test_test_info_check_invalid_argument_subtypes() -> None:
845846
_test_info_check_test_body(
846847
"""

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "mypy-pytest-plugin"
33
requires-python = ">=3.12,<3.15"
4-
version = "0.3.0"
4+
version = "0.4.0"
55
dynamic = ["dependencies"]
66

77
[tool.setuptools]

test_samples/valid_test.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,8 @@ def test_call_edge_cases() -> None:
2727
f_string = f"x{3}"
2828
list_addition = [1, 2, 3]
2929
list_addition += [4, 5, 6]
30+
31+
32+
def test_iterable_sequence_builtin() -> None:
33+
l = [1, 2, 3, 4]
34+
t = tuple(l)

tests/snapshots/mypy_test/test_check_files/invalid_test/invalid_test.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ test_samples/invalid_test.py:23: error: Argument 2 has incompatible type "tuple[
77
test_samples/invalid_test.py:30: error: Incompatible return value type (got "list[T]", expected "tuple[T, T]") [return-value]
88
test_samples/invalid_test.py:34: error: Argument 1 to "specific_test_case" has incompatible type "str"; expected "int" [arg-type]
99
test_samples/invalid_test.py:34: error: Argument 1 to "specific_test_case" has incompatible type "float"; expected "int" [arg-type]
10-
test_samples/invalid_test.py:47: error: Expected "Iterable[Any]", got "list[Any]". [iterable-sequence]
10+
test_samples/invalid_test.py:47: error: Argument has type "list[Any]"; expected "Iterable[Any]". [iterable-sequence]
1111
test_samples/invalid_test.py:47: note: This still type checks, but could be made more robust by using `iter()`
12-
test_samples/invalid_test.py:48: error: Expected "Iterable[int]", got "list[int]". [iterable-sequence]
12+
test_samples/invalid_test.py:48: error: Argument has type "list[int]"; expected "Iterable[int]". [iterable-sequence]
1313
test_samples/invalid_test.py:48: note: This still type checks, but could be made more robust by using `iter()`
1414
test_samples/invalid_test.py:61: error: Function is missing a type annotation [no-untyped-def]
1515
Found 12 errors in 1 file (checked 1 source file)

0 commit comments

Comments
 (0)