You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带关键字参数的可调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 23:33:13