Dataclasses: `No overload variant of "asdict" matches argument type "Self" [call-overload]` when deciding decorator conditionally

未关闭
#17,242 3 条评论 2 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
42/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
停滞
技术栈
python
领域
devtools

调研方向

使用 mypy 1.10.0 和 --show-error-context --strict 运行提供的 Python 3.12 示例,以复现 dataclasses.asdict 和 dataclasses.replace 的错误。首先跟踪条件 dataclass 装饰器、Self 以及已报告的重载和类型变量检查的处理。完成的标准是示例在保留运行时行为的同时通过类型检查,且不再出现这些误报。

由索引模型根据 Issue 内容生成。

描述

feature topic-dataclasses

Bug Report

Mypy raises a false positive for dataclass.asdict (No overload variant of "asdict" matches argument type "Self" [call-overload]) on the very specific circumstances:

  1. The specific decorator for dataclass is decided based on a condition (e.g. Python version)
  2. The datalcasses.asdict method is called from a method that uses PEP 673's Self Type.

I also noted a similar problem occurs for dataclasses.replace: Value of type variable "_DataclassT" of "replace" cannot be "Self" [type-var].

To Reproduce

import sys
import dataclasses
import json
from typing import Self

if sys.version_info >= (3, 10):
    dataclass = dataclasses.dataclass(kw_only=True)
else:
    dataclass = dataclasses.dataclass


@dataclass
class HelloWorld:
    a: int = 1
    b: int = 2
    c: int = 3

    def double(self) -> Self:
        fields = dataclasses.asdict(self)
        return self.__class__(**{k: v*2 for k, v in fields.items()})

    def json_overwrite(self, text: str) -> Self:
        new = json.loads(text)
        return dataclasses.replace(self, **new)

x = HelloWorld().double()
y = HelloWorld().json_overwrite('{"c": 42}')
assert x.b == 4
assert y.c == 42
print(f"{x=}")
print(f"{y=}")

Gist URL: https://gist.github.com/mypy-play/70b801fbe15391f0750be8f6c403fdf4
Playground URL: https://mypy-play.net/?mypy=latest&python=3.12&flags=show-error-context%2Cstrict&gist=70b801fbe15391f0750be8f6c403fdf4

Expected Behavior

There should be no false negative.
The program works fine in runtime:

$ python3.12 main.py
x=HelloWorld(a=2, b=4, c=6)
y=HelloWorld(a=1, b=2, c=42)

Actual Behavior

main.py: note: In member "double" of class "HelloWorld":
main.py:19: error: No overload variant of "asdict" matches argument type "Self"  [call-overload]
main.py:19: note: Possible overload variants:
main.py:19: note:     def asdict(obj: DataclassInstance) -> dict[str, Any]
main.py:19: note:     def [_T] asdict(obj: DataclassInstance, *, dict_factory: Callable[[list[tuple[str, Any]]], _T]) -> _T
main.py: note: In member "json_overwrite" of class "HelloWorld":
main.py:24: error: Value of type variable "_DataclassT" of "replace" cannot be "Self"  [type-var]
Found 2 errors in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 1.10.0
  • Mypy command-line flags: --show-error-context, --strict
  • Mypy configuration options from mypy.ini (and other config files):
  • Python version used: 3.12
主要语言
Python
星标
20.6k
派生
3.3k
平均合并
1 天 18 小时
30 天内合并 PR
54

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

python/mypy 的其他 Issue

查看 python/mypy 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。