Skip to content

Commit c6d086f

Browse files
Update plugin to support mypy 1.17.0 (#2149)
* Update Mypy version * Add logic to support mypy 1.16.0 * Use importlib's metadata to get the version * Pinned `wemake-python-styleguide` to `1.0` as per PR request * [pre-commit.ci] auto fixes from pre-commit.com hooks * Update Project configuration and dependencies lockfile * Fix all the typing reports in typesafety * Fixed multiple issues I missed in the typesafety tests update * Fixed inverted check * Update lockfile * Make Wemake Python's styleguide happy * Update minimum hypothesis version * [pre-commit.ci] auto fixes from pre-commit.com hooks * Avoid analyzing magic attributes Mypy 1.17 seems to have started analyzing a lot more attributes and some stuff does not exist in the objects checked. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent c4ce7b1 commit c6d086f

File tree

78 files changed

+803
-745
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+803
-745
lines changed

poetry.lock

Lines changed: 424 additions & 362 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ version = "0.25.0"
88
description = "Make your functions return something meaningful, typed, and safe!"
99
license = "BSD-3-Clause"
1010

11-
authors = [
12-
"sobolevn <[email protected]>",
13-
]
11+
authors = [ "sobolevn <[email protected]>" ]
1412

1513
readme = "README.md"
1614

@@ -53,16 +51,16 @@ python = "^3.10"
5351

5452
typing-extensions = ">=4.0,<5.0"
5553
pytest = { version = "^8.0", optional = true }
56-
hypothesis = { version = "^6.122", optional = true }
57-
mypy = { version = ">=1.12,<1.16", optional = true }
54+
hypothesis = { version = "^6.136", optional = true }
55+
mypy = { version = ">=1.12,<1.18", optional = true }
5856

5957
[tool.poetry.group.dev.dependencies]
6058
anyio = "^4.3"
6159
trio = ">=0.28,<0.31"
6260
attrs = ">=24.2,<26.0"
6361
httpx = "^0.28"
6462

65-
wemake-python-styleguide = "^1.0"
63+
wemake-python-styleguide = "1.0"
6664
codespell = "^2.2"
6765
slotscheck = "^0.19"
6866
ruff = ">=0.11,<0.13"
@@ -183,7 +181,9 @@ lint.per-file-ignores."tests/test_examples/test_maybe/test_maybe_pattern_matchin
183181
"D103",
184182
"F811",
185183
]
186-
lint.per-file-ignores."tests/test_examples/test_result/test_result_pattern_matching.py" = [ "D103" ]
184+
lint.per-file-ignores."tests/test_examples/test_result/test_result_pattern_matching.py" = [
185+
"D103",
186+
]
187187
lint.per-file-ignores."tests/test_pattern_matching.py" = [ "S101" ]
188188
lint.external = [ "WPS" ]
189189
lint.flake8-quotes.inline-quotes = "single"

returns/contrib/mypy/_features/kind.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from collections.abc import Sequence
22
from enum import Enum, unique
3+
from importlib.metadata import version
4+
from typing import Any
35

46
from mypy.checkmember import analyze_member_access
57
from mypy.plugin import (
@@ -61,18 +63,24 @@ def attribute_access(ctx: AttributeContext) -> MypyType:
6163
else:
6264
return ctx.default_attr_type
6365

64-
exprchecker = ctx.api.expr_checker # type: ignore
66+
mypy_version_tuple = tuple(
67+
map(int, version('mypy').partition('+')[0].split('.'))
68+
)
69+
70+
extra_kwargs: dict[str, Any] = {}
71+
if mypy_version_tuple < (1, 16):
72+
extra_kwargs['msg'] = ctx.api.msg
6573
return analyze_member_access(
6674
ctx.context.name, # type: ignore
6775
accessed,
6876
ctx.context,
6977
is_lvalue=False,
7078
is_super=False,
7179
is_operator=False,
72-
msg=ctx.api.msg,
7380
original_type=instance,
7481
chk=ctx.api, # type: ignore
75-
in_literal_context=exprchecker.is_literal_context(),
82+
in_literal_context=ctx.api.expr_checker.is_literal_context(), # type: ignore
83+
**extra_kwargs,
7684
)
7785

7886

returns/contrib/mypy/_typeops/analtype.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
from collections.abc import Sequence
2+
from importlib.metadata import version
13
from types import MappingProxyType
2-
from typing import Final, Literal, overload
4+
from typing import Any, Final, Literal, overload
35

46
from mypy.checkmember import analyze_member_access
57
from mypy.nodes import ARG_NAMED, ARG_OPT
@@ -21,7 +23,7 @@
2123
@overload
2224
def analyze_call(
2325
function: FunctionLike,
24-
args: list[FuncArg],
26+
args: Sequence[FuncArg],
2527
ctx: CallableContext,
2628
*,
2729
show_errors: Literal[True],
@@ -31,14 +33,20 @@ def analyze_call(
3133
@overload
3234
def analyze_call(
3335
function: FunctionLike,
34-
args: list[FuncArg],
36+
args: Sequence[FuncArg],
3537
ctx: CallableContext,
3638
*,
3739
show_errors: bool,
3840
) -> CallableType | None: ...
3941

4042

41-
def analyze_call(function, args, ctx, *, show_errors):
43+
def analyze_call(
44+
function: FunctionLike,
45+
args: Sequence[FuncArg],
46+
ctx: CallableContext,
47+
*,
48+
show_errors: bool,
49+
) -> CallableType | None:
4250
"""
4351
Analyzes function call based on passed arguments.
4452
@@ -48,7 +56,7 @@ def analyze_call(function, args, ctx, *, show_errors):
4856
We also allow to return ``None`` instead of showing errors.
4957
This might be helpful for cases when we run intermediate analysis.
5058
"""
51-
checker = ctx.api.expr_checker
59+
checker = ctx.api.expr_checker # type: ignore[attr-defined]
5260
with checker.msg.filter_errors(save_filtered_errors=True) as local_errors:
5361
_return_type, checked_function = checker.check_call(
5462
function,
@@ -63,7 +71,7 @@ def analyze_call(function, args, ctx, *, show_errors):
6371

6472
checker.msg.add_errors(local_errors.filtered_errors()) # noqa: WPS441
6573

66-
return checked_function
74+
return checked_function # type: ignore[no-any-return]
6775

6876

6977
def safe_translate_to_function(
@@ -110,6 +118,16 @@ def translate_to_function(
110118
This also preserves all type arguments as-is.
111119
"""
112120
checker = ctx.api.expr_checker # type: ignore
121+
122+
mypy_version = version('mypy')
123+
mypy_version_tuple = tuple(
124+
map(int, mypy_version.partition('+')[0].split('.'))
125+
)
126+
127+
extra_kwargs: dict[str, Any] = {}
128+
if mypy_version_tuple < (1, 16):
129+
extra_kwargs['msg'] = checker.msg
130+
113131
return get_proper_type(
114132
analyze_member_access(
115133
'__call__',
@@ -118,9 +136,8 @@ def translate_to_function(
118136
is_lvalue=False,
119137
is_super=False,
120138
is_operator=True,
121-
msg=checker.msg,
122139
original_type=function_def,
123140
chk=checker.chk,
124-
in_literal_context=checker.is_literal_context(),
141+
**extra_kwargs,
125142
)
126143
)

returns/contrib/mypy/returns_plugin.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,14 @@ def get_attribute_hook(
9797
self,
9898
fullname: str,
9999
) -> _AttributeCallback | None:
100-
"""Called for any exiting or ``__getattr__`` aatribute access."""
100+
"""Called for any exiting or ``__getattr__`` attribute access."""
101101
if fullname.startswith(_consts.TYPED_KINDN_ACCESS):
102+
name_parts = fullname.split('.')
103+
attribute_name = name_parts[-1]
104+
if attribute_name.startswith('__') and attribute_name.endswith(
105+
'__'
106+
):
107+
return None
102108
return kind.attribute_access
103109
return None
104110

setup.cfg

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,6 @@ strict = true
157157
strict_bytes = true
158158
warn_unreachable = true
159159

160-
# TODO: update our output assertions to match a new syntax
161-
force_uppercase_builtins = true
162-
force_union_syntax = true
163-
164160
# TODO: Enable this later, it's disabled temporarily while we don't discover why
165161
# the explicit restriction on `typeshed.stdlib.unittest.mock`,
166162
# which is the next section, is not working properly when running

tests/test_contrib/test_hypothesis/test_laws/test_custom_strategy_for_callable.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ def do_nothing(
120120
def _callable_strategy(
121121
arg1: type[object], arg2: type[object]
122122
) -> StrategyFactory[Callable]:
123-
type_arg1 = int if arg1 == Any else arg1 # type: ignore[comparison-overlap]
124-
type_arg2 = int if arg2 == Any else arg2 # type: ignore[comparison-overlap]
123+
type_arg1 = int if arg1 == Any else arg1
124+
type_arg2 = int if arg2 == Any else arg2
125125
return_results = st.functions(
126126
pure=True,
127127
returns=strategy_from_container(Result)(Result[type_arg1, type_arg2]), # type: ignore[valid-type]

tests/test_contrib/test_hypothesis/test_type_resolution.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,9 @@ def test_types_to_strategies_default() -> None: # noqa: WPS210
188188
)
189189

190190
wrapper_strategy = (
191-
"builds(from_value, shared(sampled_from([<class 'NoneType'>,"
192-
" <class 'bool'>, <class 'int'>, <class 'float'>, <class 'str'>,"
193-
" <class 'bytes'>]), key='typevar=~_FirstType').flatmap(from_type))"
191+
'builds(from_value, shared(sampled_from([NoneType,'
192+
' bool, int, float, str,'
193+
" bytes]), key='typevar=~_FirstType').flatmap(from_type))"
194194
)
195195
assert (
196196
_strategy_string(result[container_type], container_type)
@@ -214,8 +214,8 @@ def test_types_to_strategies_default() -> None: # noqa: WPS210
214214
)
215215
assert (
216216
_strategy_string(result[TypeVar], _ValueType)
217-
== "shared(sampled_from([<class 'NoneType'>, <class 'bool'>,"
218-
" <class 'int'>, <class 'float'>, <class 'str'>, <class 'bytes'>]),"
217+
== 'shared(sampled_from([NoneType, bool,'
218+
' int, float, str, bytes]),'
219219
" key='typevar=~_ValueType').flatmap(from_type).filter(lambda"
220220
' inner: inner == inner)'
221221
)
Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
- case: check_all_laws
22
disable_cache: false
33
parametrized:
4-
- container: Result
5-
- container: Maybe
6-
- container: IO
7-
- container: IOResult
8-
- container: Reader
9-
- container: ReaderResult
10-
- container: ReaderIOResult
11-
- container: ReaderFutureResult
12-
- container: Future
13-
- container: FutureResult
4+
- container: Result
5+
- container: Maybe
6+
- container: IO
7+
- container: IOResult
8+
- container: Reader
9+
- container: ReaderResult
10+
- container: ReaderIOResult
11+
- container: ReaderFutureResult
12+
- container: Future
13+
- container: FutureResult
1414
main: |
1515
from returns.context import (
1616
Reader, ReaderResult, ReaderIOResult, ReaderFutureResult,
@@ -25,14 +25,10 @@
2525
2626
x: Type[Lawful] = {{ container }}
2727
28+
2829
- case: test_all_laws_accepts_only_one_approach
2930
disable_cache: false
30-
# TODO: remove this config after
31-
# mypy/typeshed/stdlib/unittest/mock.pyi:120:
32-
# error: Class cannot subclass "Any" (has type "Any")
33-
# is fixed.
34-
mypy_config:
35-
disallow_subclassing_any = False
31+
mypy_config: disallow_subclassing_any = False
3632
main: |
3733
from hypothesis import strategies as st
3834
from returns.contrib.hypothesis.laws import check_all_laws
@@ -44,31 +40,25 @@
4440
check_all_laws(
4541
Result, use_init=True, container_strategy=st.builds(Success, st.integers())
4642
)
47-
4843
out: |
49-
main:8: error: No overload variant of "check_all_laws" matches argument types "Type[Result[_ValueType_co, _ErrorType_co]]", "bool", "SearchStrategy[Success[Any]]" [call-overload]
44+
main:8: error: No overload variant of "check_all_laws" matches argument types "type[Result[_ValueType_co, _ErrorType_co]]", "bool", "SearchStrategy[Success[Any]]" [call-overload]
5045
main:8: note: Possible overload variants:
51-
main:8: note: def [Example_co] check_all_laws(container_type: Type[Lawful[Example_co]], *, container_strategy: Union[SearchStrategy[Example_co], Callable[[Type[Example_co]], SearchStrategy[Example_co]]], settings_kwargs: Optional[Dict[str, Any]] = ..., type_strategies: Optional[Dict[Type[object], Union[SearchStrategy[Any], Callable[[Type[Any]], SearchStrategy[Any]]]]] = ...) -> None
52-
main:8: note: def [Example_co] check_all_laws(container_type: Type[Lawful[Example_co]], *, settings_kwargs: Optional[Dict[str, Any]] = ..., use_init: bool = ...) -> None
46+
main:8: note: def [Example_co] check_all_laws(container_type: type[Lawful[Example_co]], *, container_strategy: SearchStrategy[Example_co] | Callable[[type[Example_co]], SearchStrategy[Example_co]], settings_kwargs: dict[str, Any] | None = ..., type_strategies: dict[type[object], SearchStrategy[Any] | Callable[[type[Any]], SearchStrategy[Any]]] | None = ...) -> None
47+
main:8: note: def [Example_co] check_all_laws(container_type: type[Lawful[Example_co]], *, settings_kwargs: dict[str, Any] | None = ..., use_init: bool = ...) -> None
48+
5349
5450
- case: test_all_laws_requires_container_strategy
5551
disable_cache: false
56-
# TODO: remove this config after
57-
# mypy/typeshed/stdlib/unittest/mock.pyi:120:
58-
# error: Class cannot subclass "Any" (has type "Any")
59-
# is fixed.
60-
mypy_config:
61-
disallow_subclassing_any = False
52+
mypy_config: disallow_subclassing_any = False
6253
main: |
6354
from hypothesis import strategies as st
6455
from returns.contrib.hypothesis.laws import check_all_laws
6556
from returns.result import Result, Success
6657
6758
check_all_laws(Result, container_strategy=st.builds(Success, st.integers()), type_strategies={int: st.integers()})
6859
check_all_laws(Result, type_strategies={int: st.integers()})
69-
7060
out: |
71-
main:6: error: No overload variant of "check_all_laws" matches argument types "Type[Result[_ValueType_co, _ErrorType_co]]", "Dict[Type[int], SearchStrategy[int]]" [call-overload]
61+
main:6: error: No overload variant of "check_all_laws" matches argument types "type[Result[_ValueType_co, _ErrorType_co]]", "dict[type[int], SearchStrategy[int]]" [call-overload]
7262
main:6: note: Possible overload variants:
73-
main:6: note: def [Example_co] check_all_laws(container_type: Type[Lawful[Example_co]], *, container_strategy: Union[SearchStrategy[Example_co], Callable[[Type[Example_co]], SearchStrategy[Example_co]]], settings_kwargs: Optional[Dict[str, Any]] = ..., type_strategies: Optional[Dict[Type[object], Union[SearchStrategy[Any], Callable[[Type[Any]], SearchStrategy[Any]]]]] = ...) -> None
74-
main:6: note: def [Example_co] check_all_laws(container_type: Type[Lawful[Example_co]], *, settings_kwargs: Optional[Dict[str, Any]] = ..., use_init: bool = ...) -> None
63+
main:6: note: def [Example_co] check_all_laws(container_type: type[Lawful[Example_co]], *, container_strategy: SearchStrategy[Example_co] | Callable[[type[Example_co]], SearchStrategy[Example_co]], settings_kwargs: dict[str, Any] | None = ..., type_strategies: dict[type[object], SearchStrategy[Any] | Callable[[type[Any]], SearchStrategy[Any]]] | None = ...) -> None
64+
main:6: note: def [Example_co] check_all_laws(container_type: type[Lawful[Example_co]], *, settings_kwargs: dict[str, Any] | None = ..., use_init: bool = ...) -> None

typesafety/test_curry/test_curry/test_curry_arguments.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@
5858
reveal_type(MyClass(test)) # N: Revealed type is "main.MyClass[Overload(def (a: builtins.int) -> Overload(def (b: builtins.int, c: builtins.str) -> builtins.int, def (b: builtins.int) -> def (c: builtins.str) -> builtins.int), def (a: builtins.int, b: builtins.int) -> def (c: builtins.str) -> builtins.int, def (a: builtins.int, b: builtins.int, c: builtins.str) -> builtins.int)]"
5959
6060
61-
# TODO: remove skip after this bug in `mypy` is fixed:
62-
# https://github.com/python/mypy/issues/8801
6361
- case: curry_init_magic_method
6462
disable_cache: false
6563
skip: true
@@ -71,7 +69,7 @@
7169
def __init__(self, arg: int, other: str) -> None:
7270
...
7371
74-
reveal_type(Test) # N: Revealed type is "Overload(def (arg: builtins.int) -> def (other: builtins.str) -> ex.Test, def (arg: builtins.int, other: builtins.str) -> ex.Test)"
72+
reveal_type(Test) # N: Revealed type is "Overload(def () -> main.Test, def (arg: builtins.int) -> main.Test, def (arg: builtins.int, other: builtins.str) -> main.Test)"
7573
7674
7775
- case: curry_call_magic_method

0 commit comments

Comments
 (0)