
Ruff 类型检查器如何内置标准库类型桩ty_vendored 与 typeshed 的打包、加载与自动同步机制【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff本文以 Ruff 仓库中 crates/ty_vendored/README.md 为骨架深入讲解 Rust 编写的类型检查器 ty 如何将 Python 官方类型桩仓库 typeshed 的标准库 stub 完整搬运进自身二进制包括构建期的 ZIP 打包、运行期的只读虚拟文件系统、ty_extensions扩展包注入、补丁机制以及基于 GitHub Actions 的双周自动同步流水线。读完本文你将掌握 ty_vendored 从源码目录到VendoredFileSystem的完整链路并能在本地复现、验证与手动触发整条同步流程。一、为什么类型检查器需要 vendored typeshedPython 标准库os、sys、functools等的绝大多数实现由 C 或动态代码构成类型检查器无法直接对运行时源码做静态分析。为此Python 社区维护着 typeshed——一套用.pyistub 文件描述标准库与第三方库类型的官方仓库。ty 作为 Ruff 内置的类型检查器需要在不依赖用户本机 Python 环境的情况下完成对import os、from functools import ...等标准库导入的类型解析因此必须把 typeshed 的标准库 stub 随二进制一起分发。ty_vendored就是这个内部组件 crate它把 typeshed 的标准库 stub 原样复制进仓库vendoring并在构建时打包为 zip、在运行时暴露为一个只读文件系统供 ty 的模块解析与语义分析使用。在 Cargo.toml 中该 crate 的定位写得非常直白description This is an internal component crate of Ruff它本身不对外提供命令行能力而是被上层 crate 直接依赖。二、仓库布局stub、扩展包与补丁三块拼图ty_vendoredcrate 的完整目录结构如下可对照 crates/ty_vendored 查看crates/ty_vendored/ ├── Cargo.toml # crate 元数据与依赖、zstd/deflate 特性开关 ├── README.md # 本文所依据的文档 ├── build.rs # 构建脚本把 vendor/typeshed 打包成 zip ├── src/lib.rs # 运行期入口SOURCE_COMMIT 常量与 file_system() ├── vendor/typeshed/ # 被 vendor 的 typeshed 标准库 stub构建期输入 │ ├── LICENSE │ ├── README.md │ ├── source_commit.txt # 记录对应的 typeshed commit SHA │ └── stdlib/ # 标准库 .pyi 桩文件 ├── ty_extensions/ # ty 自有的扩展 stub 包构建期注入到 stdlib │ ├── README.md │ ├── __init__.pyi │ ├── _internal.pyi │ └── pydantic.pyi └── typeshed_patches/ # 同步完成后自动打上的补丁 ├── README.md └── *.patch # 例如 0001-dict-get-object.patch其中vendor/typeshed/source_commit.txt是精确版本追踪的关键它保存着当前 vendored stub 所对应的 typeshed 提交 SHA本仓库当前记录为bc016545988403f13b2dd9b56e88b931683c80b1。README 明确指出通过该文件即可反查我们的 stub 与 typeshed 上游的哪个提交对应。三、构建期build.rs 如何把整棵 typeshed 树塞进一个 zipty_vendored的打包逻辑完全发生在构建期位于 crates/ty_vendored/build.rs。该脚本的核心函数是write_zipped_typeshed_to工作流程如下递归遍历vendor/typeshed目录常量TYPESHED_SOURCE_DIR把每个文件与目录写入ZipWriter路径统一为/分隔符使用path_slash将相对路径转换为斜杠形式避免 Windows 反斜杠带来的跨平台差异按特性选择压缩算法开启zstd特性默认→ 使用CompressionMethod::Zstd仅开启deflate→ 使用CompressionMethod::Deflated该分支专为 WASM 构建设计因为编译zstd-sys需要 clang会显著复杂化 WASM 的构建链两者都关闭 → 退回CompressionMethod::Stored不压缩。 压缩选项统一设置 Unix 权限0o644动态打补丁当写入到stdlib/VERSIONS时追加一行ty_extensions: 3.0-让ty_extensions作为可被解析的标准库模块注册注入ty_extensions包通过常量表TY_EXTENSIONS_STUBS把ty_extensions/__init__.pyi、_internal.pyi、pydantic.pyi三个文件从 crate 目录复制进 zip 的stdlib/ty_extensions/下。最终 zip 输出到OUT_DIR/zipped_typeshed.zip。构建脚本还带有自我保护断言如果vendor/typeshed目录不存在main()会直接 panic 并提示 Where is typeshed?从而保证 zip 产物不会静默缺失输入。3.1 构建期产物如何进入二进制build.rs只负责产出 zip 文件真正把它嵌入二进制的是 crates/ty_vendored/src/lib.rspub const SOURCE_COMMIT: str include_str!(../vendor/typeshed/source_commit.txt).trim_ascii_end(); static_assertions::const_assert_eq!(SOURCE_COMMIT.len(), 40); static TYPESHED_ZIP_BYTES: [u8] include_bytes!(concat!(env!(OUT_DIR), /zipped_typeshed.zip)); pub fn file_system() - static VendoredFileSystem { static VENDORED_TYPESHED_STUBS: LazyLockVendoredFileSystem LazyLock::new(|| VendoredFileSystem::new_static(TYPESHED_ZIP_BYTES).unwrap()); VENDORED_TYPESHED_STUBS }两个include_*!宏把构建期的文本与二进制产物直接烙进编译后的可执行文件SOURCE_COMMIT暴露 typeshed 上游提交 SHA并用static_assertions在编译期断言其长度为 40 位即标准 SHA-1 长度TYPESHED_ZIP_BYTES则是整个 zip 的字节切片。file_system()通过LazyLock只初始化一次VendoredFileSystem之后全局复用。四、运行期VendoredFileSystem——一个只读的 zip 虚拟文件系统VendoredFileSystem定义于 crates/ruff_db/src/vendored.rs其设计目标是让 ty 的模块解析代码以与真实磁盘文件系统一致的 API访问 zip 内的 stub同时保证只读与不可变。关键设计点包括路径归一化NormalizedVendoredPath会去除./..组件、剥离尾部斜杠并在 Windows 上把\统一归一化为/见 crates/ruff_db/src/vendored/path.rs 中的VendoredPath/VendoredPathBuf。由于 zip 内部用尾部斜杠区分目录与文件exists()、metadata()等方法会同时探测stdlib与stdlib/两种写法只读语义只提供exists、metadata、is_directory、is_file、read_to_string、read_directory等查询方法没有写入能力Metadata携带由 zip 条目 CRC32 派生的FileRevision可供下游做缓存失效判断免拷贝并发读取archive_reader()克隆ZipArchive而非复制 zip 字节每个读取操作持有独立游标可并发解压不同文件构建辅助器VendoredFileSystemBuilder支持以指定压缩算法如Stored组装虚拟文件系统测试代码用它构造stdlib/functools.pyi、stdlib/asyncio/tasks.pyi等小型 mock typeshed 来验证 API 行为。4.1 上层消费方ty 语义数据库如何挂载 vendored 文件系统在 crates/ty_python_semantic/src/db.rs 的测试数据库TestDb中可以看到典型用法let vendored ty_vendored::file_system().clone();TestDb把VendoredFileSystem作为 salsa 数据库的字段持有ProgramSettings::empty(vendored)用它初始化模块解析上下文crates/ty_python_semantic/tests/corpus.rs 中的测试环境同样通过ty_vendored::file_system().clone()挂载 vendored stub。由此可以推断ty 的模块解析器把 zip 内的stdlib/目录视作一个内置的、永远可用的搜索路径无论用户本机是否安装了 Python 或 typeshed。五、ty_extensionstypeshed 之外的 ty 私有类型语言扩展纯 typeshed stub 只能描述标准库长什么样而 ty 还引入了若干自有类型系统特性如Not、Intersection、Top、Bottom、Unknown等特殊形式因此需要通过ty_extensions包为这些符号提供定义与文档。ty_extensions/README.md 说明build.rs会将此目录中的 stub 作为 vendored 的ty_extensions包打包进vendor/typeshed/stdlib使其对外表现为标准库的一部分ty_extensions/init.pyi 面向终端用户定义了static_assert、Not、Intersection、Top、Bottom、AlwaysTruthy、AlwaysFalsy、JustFloat/JustComplex、NamedTupleLike等公开 API每个符号都附有详尽的类型论语义文档ty_extensions/_internal.pyi 是内部实现TypeOf、CallableTypeOf、Unknown、Todo、Divergent等特殊形式以及ConstraintSet、is_subtype_of、is_assignable_to等类型系统测试辅助 API注释明确仅供 ty 内部测试使用终端用户不应直接导入ty_extensions/pydantic.pyi 则建模了 Pydantic 宽松lax模式下的输入类型别名LaxBool、LaxInt、LaxDate等供对 Pydantic 做特殊建模时引用。同时build.rs 会在打包时向stdlib/VERSIONS追加ty_extensions: 3.0-条目确保ty_extensions能被类型检查器当作标准库模块正常解析。六、typeshed_patches同步后的定点修复typeshed 是通用开源项目个别 stub 的定义不一定完全符合 ty 的语义需求因此 ty_vendored 维护了一套补丁目录 typeshed_patches。目录内当前包含0001-dict-get-object.patch、0002-mapping-get-object.patch、0003-dict-view-isdisjoint-object.patch、0004-dict-pop-object.patch、0007-dataclass-transform-unknown-arguments.patch等补丁文件。typeshed_patches/README.md 明确了补丁的使用纪律补丁由自动化同步工作流在 docstring 注入与格式化之后应用每个补丁都以 typeshed 仓库根目录为基准rooted at the typeshed repository必须能干净地应用apply cleanly工作流在应用补丁前会先把未打补丁的同步分支推送到远端这样一旦某个补丁失败维护者可以直接在该分支上手工修复而无需重跑整条同步流水线。七、双周自动同步sync_typeshed.yaml 完整流水线README 的核心承诺是stub 每两周通过sync_typeshed.yaml自动 PR 更新一次且可随时通过 workflow dispatch 手动触发。该工作流位于 .github/workflows/sync_typeshed.yaml触发方式为定时触发schedule下的 cron 表达式0 0 1,15 * *——即每月 1 日与 15 日零点各运行一次对应每两周的节奏手动触发在 GitHub Actions 页面使用workflow_dispatch按钮随时运行。整条流水线由 6 个 job 串联设计上刻意利用多平台 runner 来补全 docstringJob运行平台职责syncLinuxcheckout Ruff 与 typeshed删除旧 stub复制typeshed/stdlib到vendor/typeshed写入source_commit.txt创建并推送typeshedbot/sync-typeshed分支随后运行scripts/codemod_docstrings.sh同步 Linux 可用的 docstringdocstrings-windowsWindows基于上游分支继续跑 docstring 脚本补齐 Windows 专属 docstring提交推送docstrings-macosmacOS补齐 macOS 专属 docstring用 black配置来自同步时临时复制的 typeshedpyproject.toml重新格式化 stub删除临时 pyproject然后git apply --directorycrates/ty_vendored/vendor/typeshed应用全部补丁并单独提交update-snapshotsLinux尽力而为continue-on-error: true运行cargo insta test --accept更新测试快照失败/超时不阻塞后续步骤create-prLinux在main分支上创建标题为[ty] Sync vendored typeshed stubs的 PR已有同源 PR 则跳过create-issue-on-failureLinux仅定时任务场景下若上述关键 job 失败自动在仓库创建Automated typeshed sync failed ...的 issue 告警工作流还做了一些工程化细节UPSTREAM_BRANCH: typeshedbot/sync-typeshed统一各 job 的共享分支所有 cron 任务在 fork 仓库上跳过github.repository astral-sh/ruff || github.event_name ! scheduleupdate-snapshots故意不阻塞 PR 创建避免快照问题拖死整个同步。八、如何本地查看与验证 vendored stub由于vendor/typeshed与打包产物均位于仓库内无需任何网络访问即可验证查看当前 stub 版本读取 crates/ty_vendored/vendor/typeshed/source_commit.txt得到 typeshed 上游 commit SHA查看具体 stub 内容直接浏览 crates/ty_vendored/vendor/typeshed/stdlib 下的.pyi文件本地构建验证打包链路在仓库根目录执行cargo build -p ty_vendored构建成功后OUT_DIR内会生成zipped_typeshed.zip若vendor/typeshed缺失构建会因build.rs的断言直接失败运行 crate 自带测试cargo test -p ty_vendored会执行 crates/ty_vendored/src/lib.rs 中的两个核心测试typeshed_zip_created_at_build_time打开构建期生成的 zip断言stdlib/functools.pyi存在且内容包含def update_wrapper(typeshed_vfs_consistent_with_vendored_stubs用walkdir遍历磁盘上的vendor/typeshed目录逐一断言每个路径都能在VendoredFileSystem中命中且文件/目录类型一致——这条测试从机制上保证了源码树与 zip 内文件系统永远同步运行上层语义测试cargo test -p ty_python_semantic会经由 crates/ty_python_semantic/tests/corpus.rs 间接挂载ty_vendored::file_system()验证标准库类型解析链路。九、小结一个构建期打包 运行期只读挂载 双周自动同步的完整闭环从 crates/ty_vendored/README.md 的三段简介出发结合仓库源码可以看到 ty_vendored 的完整工程闭环来源typeshed 上游标准库 stub含精确 commit 追踪加上 ty 自有的ty_extensions扩展包与定点补丁打包build.rs在构建期按特性选择 zstd/deflate/stored 压缩把整棵 stub 树压成 zip 并通过include_bytes!嵌入二进制加载lib.rs用LazyLock将 zip 字节初始化为全局唯一的VendoredFileSystem上层 ty 模块解析器把它当作内置标准库搜索路径保鲜sync_typeshed.yaml每两周自动执行多平台 docstring 同步、格式化、打补丁、更新快照并提交 PR也支持随时手动触发兜底构建断言与一致性测试保证目录树与 zip 内文件系统不会分叉。这套机制让 ty 在不依赖用户本机任何 Python 安装的前提下依然拥有完整、可版本追踪、可审计的标准库类型信息是 Ruff 类型检查器能够开箱即用的重要基石。【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考