带有关键字参数的可调用 pytest 夹具会导致 mypy linting 错误

问题描述 投票:0回答:1

我有以下设置:

@pytest.fixture
def check_answer() -> t.Callable[[dict[str, t.Any], dict[str, t.Any], int], None]:
    def _check(
        first_response: dict[str, t.Any],
        second_response: dict[str, t.Any],
        named_optional_arg: int = 1,
    ) -> None:
        
        *assert stuff*

    return _check

然后我将

check_answer
作为参数传递给
test_my_answer
,我想将其称为
check_answer(ans1, ans2, named_optional_arg=5)
。可选参数很少使用,因此在调用该名称时存在该名称很重要,但是,当我包含该名称时,由于意外的关键字参数,我从 mypy 中收到错误。

python pytest mypy
1个回答
0
投票

问题在于您的类型签名不够具体,无法捕获

_check
具有
named_optional_arg
的事实。
Callable
不足以输入关键字参数,这就是必须使用回调协议的地方:

from collections.abc import Mapping
from typing import Protocol, Any

class Checker(Protocol):
    def __call__(
        self,
        first_response: Mapping[str, Any],
        second_response: Mapping[str, Any],
        /,
        *,
        named_optional_arg: int = ...
    ):
        ...

您可以阅读*(单星)和/(斜杠)作为独立参数做什么?,了解如何在参数列表中使用

/
*
来描述函数的确切方式的更多信息允许被调用。在这种情况下,我已经做到了,前两个参数必须由位置指定,第三个可选参数必须由名称指定。

此外,请注意,我将

dict
替换为
Mapping
。这是因为检查/断言只需要读取响应,而不需要写入响应。

然后您可以将声明更改为:

@pytest.fixture
def check_answer() -> Checker:
    ...
© www.soinside.com 2019 - 2024. All rights reserved.