尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Ruff 类型检查器中的全局常量:`__debug__` 的类型建模与 mdtest 验证

Ruff 类型检查器中的全局常量:`__debug__` 的类型建模与 mdtest 验证 Ruff 类型检查器中的全局常量__debug__的类型建模与 mdtest 验证【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff__debug__是 Python 为数不多由解释器内置的全局常量之一它的类型推断结果会直接进入类型检查器的全局符号表。本文以仓库中的测试文档 crates/ty_python_semantic/resources/mdtest/scopes/global-constants.md 为主体结合 Ruff 类型检查器ty的源码实现完整剖析__debug__在任意作用域内全局可用、类型恒为bool这一语义是如何定义、实现并被自动化测试锁定的读完你既能理解这类隐式全局符号的建模原理也能掌握 mdtest 这一文档即测试doctest 风格的用法并复现对应的reveal_type/# error:断言。一、关联文档一个关于全局常量的 mdtest 测试用例本文依托的原始文档位于 crates/ty_python_semantic/resources/mdtest/scopes/global-constants.md。它属于 ty 语义分析 cratety_python_semantic下的 mdtest 测试语料与scopes/目录中global.md、builtin.md、nonlocal.md、moduletype_attrs.md等测试文件同族专门验证各种作用域scope行为。该文档全文如下Global Constants__debug__constantThe__debug__constant should be globally available:reveal_type(__debug__) # revealed: bool def foo(): reveal_type(__debug__) # revealed: bool别看它短它其实是两条严格的、可执行的断言模块作用域module scope下__debug__可直接引用且推断类型为bool函数作用域function scope下def foo()内部__debug__依然可直接引用且类型为bool即全局可用globally available不仅指模块顶层还包括嵌套作用域中的名称解析。文档标题取作 Global Constants全局常量其后续章节专门针对__debug__展开作为这一类别在当前测试语料中的代表用例。与之呼应的还有 crates/ty_python_semantic/resources/mdtest/known_constants.md它覆盖了另一类已知常量如typing.TYPE_CHECKING被建模为Literal[True]两者共同勾勒出 ty 对名字固定、语义预知常量的处理策略。二、__debug__的运行时语义在展开实现细节之前先明确__debug__在 Python 运行时的行为这也是类型检查器建模的依据它是一个内置常量在解释器启动时被设定取值只可能是True或False默认不带优化标志情况下其值为True当解释器以-O或-OO优化模式启动时其值为False同时断言语句assert会被移除它是只读的在源码层面用户无法对其赋值或重新绑定。正因如此类型检查器既不能把__debug__固定为Literal[True]-O下运行时是False也不能把它当成普通的可重绑定变量而应建模为一个类型为bool的全局常量。这与typing.TYPE_CHECKING类型检查期间恒为真被建模为Literal[True]见 known_constants.md形成了鲜明对照一个是运行期常量、类型用宽泛的bool一个是类型检查期常量、类型用最窄的Literal[True]。三、源码实现隐式全局符号的查找路径__debug__的全局可用在 ty 中并非通过普通模块赋值产生而是由源码里的隐式全局符号implicit global symbol机制提供。核心实现在 crates/ty_python_semantic/src/place.rs 的module_type_implicit_global_symbol函数中。该函数的文档注释place.rs指出隐式全局符号是__doc__、__name__、__file__这类在每个模块全局作用域中隐式定义的符号由于类型恒定查找时直接按types.ModuleType实例上的成员处理。其中__debug__被单独特判__debug__ Place::bound(KnownClass::Bool.to_instance(db, env)).into(),见 place.rs这一行完成了两件事将__debug__解析为**已绑定bound**的占位符Place而不是未定义Undefined因此任意作用域内引用它都不会触发未解析引用unresolved-reference类诊断将其类型绑定为KnownClass::Bool的实例即bool与 mdtest 中# revealed: bool的断言完全一致。同一个match中还有一组同族特判可帮助理解隐式全局符号的完整清单place.rs__file__→str即使 typeshed 标注为str | None模块内查到自己恒为字符串__doc__→ 有模块 docstring 时收窄为str否则回退到 typeshed 的str | None__builtins__→Any__warningregistry__→dict[Any, int]且标记为可能未绑定由 warnings 机制惰性创建__annotate__→ 仅 Python 3.14 存在建模为一个可调用对象(format: int) - dict[str, Any]同样标记为可能未绑定。此外place.rs 中的all_implicit_module_globals会遍历特判符号 ModuleType体作用域声明符号供全局作用域的补全等功能使用其中特判符号列表显式包含__builtins__、__debug__、__warningregistry__三个place.rs再次印证__debug__是绕过 typeshed、由检查器直接建模的常量。需要注意一个实现细节源码注释中有明确说明module_type_implicit_global_symbol只应作为同文件内全局作用域查找的回退路径如果是跨文件引用例如from other import __debug__则应走imported_symbol或类似逻辑。这与 mdtest 中在同一个文件里、不同作用域下都能直接引用的测试场景严格对应。四、写入保护对__debug__赋值是语法错误全局可用的另一面是不可写。在 crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md 的 Write to debug 一节测试文档明确声明The special Python builtin__debug__should not be modified.并给出三条断言覆盖三种不同的写入形态# error: [invalid-syntax] cannot assign to __debug__ __debug__ False # error: [invalid-syntax] cannot assign to __debug__ def process(__debug__): pass # error: [invalid-syntax] cannot assign to __debug__ class Generic[__debug__]: pass这三条用例说明无论是直接赋值、把__debug__用作函数参数名还是用作泛型类型参数名class Generic[__debug__]对应 Python 3.12 的 PEP 695 语法ty 都会报出invalid-syntax规则、消息为 cannot assign to debug 的诊断。值得注意的是该用例文件头部声明了python-version 3.12见 semantic_syntax_errors.md说明测试按特定解释器版本语境执行这也是 mdtest 通过[environment]toml 配置控制运行环境的典型用法。五、mdtest 框架Markdown 即测试注释即断言要读懂并复跑上述用例需要了解global-constants.md所依赖的 mdtest 机制。根据 crates/ty_test/README.md 的说明任何 Markdown 文件都可以是一个测试套件只要ty_test::run以该文件路径调用即可执行crates/ty_python_semantic/tests/mdtest.rs就是把resources/mdtest/目录下所有 Markdown 文件批量当作测试套件的入口一个测试由若干个 fenced code block 组成语言标签支持pyPython 文件、pyistub、ipynbNotebook、toml配置断言以 Python 注释形式书写共两类# revealed: 类型必须与reveal_type(...)诊断输出中类型的显示形式完全一致例如# revealed: bool# error: [规则码]/# error: 文本/# error: 列号 [规则码] 文本断言在指定行会触发指定规则的诊断。回到本文主题的用例reveal_type(__debug__) # revealed: bool断言了推断类型的精确显示值reveal_type在测试环境中被当作内建可用不导入typing.reveal_type也能用只是会额外产生一条未导入的提示诊断。运行整组测试即可通过标准方式执行cargo test -p ty_python_semantic让所有 Markdown 用例包括global-constants.md自动执行、逐条比对断言任何一个断言与诊断不匹配都会导致测试失败。六、从实现到测试一条完整的验证链路综合本文内容可以看到__debug__这一全局常量在 Ruff 类型检查器中被完整覆盖维度行为依据可用性模块/函数作用域内均可直接引用不报未定义global-constants.md 中的reveal_type断言类型恒为bool非字面量类型place.rs 的KnownClass::Bool特判写入赋值、作参数名、作类型参数名均报invalid-syntaxsemantic_syntax_errors.md 的 Write to debug 用例建模类别属于隐式模块全局符号与__doc__、__name__、__file__同族place.rs 的函数注释与all_implicit_module_globals特判列表这条链路体现了 ty 项目以 mdtest 为行为规范、以源码为实现、以 snapshots/断言为回归防线的开发方式行为先在 resources/mdtest 中以可读的 Markdown 写成预期实现代码place.rs中的特判分支再保证这些预期成立最终由测试入口持续守护防止后续改动破坏__debug__的全局可用性与类型稳定性。七、延伸阅读如果想进一步了解全局常量/隐式符号相关的完整建模建议顺藤摸瓜阅读以下文件crates/ty_python_semantic/resources/mdtest/known_constants.mdtyping.TYPE_CHECKING等已知常量如何被建模为Literal[True]以及与用户自定义TYPE_CHECKING的交互规则crates/ty_python_semantic/resources/mdtest/scopes/builtin.md内建作用域builtin scope中名称查找与局部/全局遮蔽的测试crates/ty_python_semantic/resources/mdtest/scopes/moduletype_attrs.mdModuleType成员作为隐式全局符号的测试crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md包括Write to debug在内的语法语义错误用例全集crates/ty_test/README.mdmdtest 断言语法revealed/error的完整规范。通过这些材料你可以完整复现reveal_type(__debug__) # revealed: bool这一行为并理解类型检查器在处理语言内建全局常量时的通用建模思路。【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表