
开发者发布 Gawain 工具,强制 Python 所有变量标注类型
来源标题:Show HN: Gawain – Require type hints on all Python variables
Gawain 要求 Python 代码中的变量、参数、返回值和类属性都必须有类型注解,再调用 ty 或 pyrefly 做类型检查。作者称开发原因是反感 dict[str, Any];现有的 ruff ANN 和 flake8-annotations 只覆盖函数。Gawain 会对未标注的变量和类属性报出 GW001 等错误。
以下正文由 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 说明了如何切换。 pip install gawain 不带 extra 时只会安装 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,并使用 Astral 的 ty 或 Meta 的 pyrefly 检查类型。 我不知道,我就是喜欢亚瑟王传说。Gawain 是圆桌骑士之一,吉祥物是《高文爵士与绿骑士》中绿骑士的斧头,配着绿色腰带。
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。