带关键字参数的可调用pytest fixture引发mypy linting错误
解决pytest Fixture调用时mypy报「意外关键字参数」错误
问题原因
你当前的check_answer fixture返回类型用了t.Callable[[dict[str, t.Any], dict[str, t.Any], int], None],这个类型注解只能描述三个位置参数,无法体现第三个参数是「带默认值、必须以关键字形式传入」的参数,所以mypy识别不到named_optional_arg这个关键字参数的合法性,触发错误。
解决方案:用typing.Protocol精确描述调用签名
typing.Callable的表达能力有限,无法定义带关键字约束的参数签名,改用Protocol可以精确匹配你的函数调用要求,同时强制named_optional_arg必须以关键字传入:
步骤1:定义协议类
import pytest from typing import Protocol, Dict, Any class AnswerChecker(Protocol): def __call__( self, first_response: Dict[str, Any], second_response: Dict[str, Any], *, # 强制后续参数必须用关键字传入 named_optional_arg: int = 1, ) -> None: ...
步骤2:修改Fixture的返回类型
@pytest.fixture def check_answer() -> AnswerChecker: def _check( first_response: Dict[str, Any], second_response: Dict[str, Any], *, named_optional_arg: int = 1, ) -> None: # 你的断言逻辑示例 assert first_response.get("code") == second_response.get("code") assert named_optional_arg > 0 return _check
步骤3:调用Fixture(符合要求且通过mypy检查)
def test_my_answer(check_answer): ans1 = {"code": 200, "data": []} ans2 = {"code": 200, "data": []} # 必须指定参数名,符合你的需求 check_answer(ans1, ans2, named_optional_arg=5)
临时替代方案(不推荐)
如果不想引入Protocol,可以临时用t.Callable[..., None]作为返回类型屏蔽错误,但这样会丢失所有参数的类型校验,仅适合快速临时调试:
@pytest.fixture def check_answer() -> t.Callable[..., None]: # 内部函数保持不变 ...
内容的提问来源于stack exchange,提问作者duckasaur
相关产品推荐
相关产品推荐

