
Gawain 工具要求为所有 Python 变量添加类型注解
来源标题:Show HN: Gawain – Require type hints on all Python variables
开发者发布 Gawain,一款强制要求 Python 代码中所有变量、参数、返回值和类属性都标注类型注解的工具,随后调用 ty 或 pyrefly 检查类型是否正确。现有的 ruff ANN 规则和 flake8-annotations 只要求函数加注解,Gawain 把范围扩大到变量和类属性。作者称做这个工具是因为讨厌 dict[str, Any]。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
gawain 要求对 Python 代码中的变量、参数、返回值和类属性都加上类型注解,然后运行类型检查器 ty 或 pyrefly,检查这些类型是否正确。mypy、Pyright、ty 和 pyrefly 这类类型检查器会对没有注解的变量推断类型。ruff 的 ANN 规则和 flake8-annotations 只要求函数上有注解。gawain 还要求变量和类属性上也有注解。我做 gawain 只是因为我讨厌 dict[str, Any],想为此做点什么。如果你对此的回答是“但 Python 已经能推断出来”或“但我的 IDE 会帮我推断”,那就别用它,小学徒。
PORT = 8080
retries = 3
total = compute()
def send(to, body): print(f"to {to}: {body}")
class Order: def init(self, items: list[str]) -> None: self.items = items
gawain check shop.py 会输出:
[presence] shop.py:1:1 GW001 variable 'PORT' has no type annotation shop.py:3:1 GW001 variable 'total' has no type annotation shop.py:6:5 GW003 function 'send' has no return type annotation shop.py:6:10 GW002 parameter 'to' of function 'send' has no type annotation shop.py:6:14 GW002 parameter 'body' of function 'send' has no type annotation shop.py:12:14 GW004 attribute 'items' is not declared in the body of class 'Order' 6 errors (presence). Type check skipped until presence errors are fixed.
retries = 3 能通过,因为字面量的类型很明显。PORT 是常量,所以需要 Final[int]。当所有注解都到位后,gawain 会对同样的文件运行类型检查器,并打印它报告的内容。以默认的 ty 为例,对于 prices.py:
def total(prices: list[int]) -> int: return "0"
[types]
prices.py:2:12 ty[invalid-return-type] Return type does not match returned value: expected int, found Literal["0"]
1 error (types).
安装 安装 gawain 时,附带你想要的那款类型检查器的 extra。ty 是默认检查器,ty extra 会把它固定到 0.0.100:
uv tool install "gawain[ty]"
或
pip install "gawain[ty]"
要改用 pyrefly,就安装 pyrefly extra,它会把 pyrefly 固定到 1.4.1,并且不会安装 ty:
uv tool install "gawain[pyrefly]"
或
pip install "gawain[pyrefly]"
然后在 [tool.gawain] 中设置 checker = "pyrefly",或用 --checker pyrefly 来选择它。docs/configuration.md 说明了这个切换。
不带 extra 的 pip install gawain 只会安装 gawain 命令。之后它需要 PATH 上有一个检查器,或者用 --no-types 只运行注解检查。
使用 gawain 时要小心。ty 处于 beta 阶段,它的诊断信息可能随版本变化。如果这对你的项目是个问题,就用 pyrefly,或者用 --no-types 只运行注解检查。
gawain check src/ # 先注解,再类型 gawain check src/ --no-types # 只检查注解 gawain check src/ --checker pyrefly # 用 pyrefly 代替 ty gawain check src/ --mode strict # 每个赋值都要有注解 gawain check src/ --format json # 输出一个 JSON 对象,供工具使用
gawain 在没有报告任何问题时以 0 退出,报告错误时以 1 退出,用法错误或类型检查器无法运行时以 2 退出。类型检查器的警告会被打印出来,但不会导致检查失败。
代码 报告 GW001 没有注解的变量赋值。 GW002 没有注解的参数。 GW003 没有返回注解的函数。 GW004 没有注解的类属性,或者类体中没有声明的 self.x。 GW010 没有注解为 Final[T] 的常量。 GW011 没有类型的裸 Final。 GW020 注解中的 Any。
GW000 标记 gawain 无法读取的文件,GW900 和 GW901 标记损坏或未使用的抑制。要让某一行静默,请写出代码名:
value = load() # gawain: ignore[GW001]
docs/rules.md 有完整的规则、豁免和抑制语法。
默认模式是 obvious。当一个名称的值类型很明显,并且该名称之后不再被赋值时,它可以不带注解:字面量(count = 0)、字面量容器(ids = [1, 2, 3])或构造函数调用(user = User("ada"))。strict 要求每个赋值都有注解:
[tool.gawain] mode = "strict"
docs/rules.md 有每种模式的确切规则。
repos:
- repo: https://github.com/matheuzgomes/gawain
rev: v0.3.0
hooks:
- id: gawain
pre-commit 会从这个仓库的源码安装钩子,所以构建它需要 Rust 1.97 或更新版本。docs/configuration.md 详细介绍了 [tool.gawain]、路径和钩子。
在 CPython 3.14 标准库(1,847 个文件,974,586 行)上,30 次运行的中位数(flake8-annotations 为 5 次):gawain 以 --no-types 运行。这是在单台机器(AMD Ryzen 7 3700X,WSL2)上的一个基准测试。docs/benchmarks.md 有版本号和可再次运行的命令。
docs/rules.md:规则、模式、豁免和抑制。 docs/configuration.md:路径、输出、退出码、[tool.gawain] 和 pre-commit。 docs/benchmarks.md:上述数字是如何测量的。
致谢 gawain 使用 ruff_python_parser 读取 Python,并使用 ty(均由 Astral 开发)或 pyrefly(由 Meta 开发)检查类型。
我不知道,我就是喜欢亚瑟王的故事。Gawain 是圆桌骑士之一,吉祥物是《高文爵士与绿骑士》中绿骑士的斧头配绿色腰带。
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。