- 包管理器
- 开发工具
【免费下载链接】pip
The Python package installer
本文是面向 pip(Python 包安装器)开发者的贡献指南,覆盖 PR 提交规范、AI 生成代码政策、自动化测试、NEWS 变更日志条目的编写规则、分支同步工作流,以及从贡献者走向维护者的成长路径。读完本文,你将掌握在 pip 仓库(根目录即本仓库,源码位于 src/pip)中提交合规且可被快速合并的 Pull Request 的完整实操流程,并能独立完成一条符合 towncrier 规范的 NEWS 条目。
pip 内部架构导读
在深入贡献之前,建议先了解 pip 的内部结构。pip 有一个持续更新的 内部架构指南,包含总体概览(overview)、源码解剖(anatomy)、配置文件体系、包查找(package-finding)、命令行接口设计与升级选项等子章节,在你初次接触代码库时非常有帮助。
从源码目录结构看,pip 的核心实现集中在 src/pip/_internal 下,按职责拆分为cli(命令行解析)、commands(各子命令实现)、index(包索引与查找)、metadata(包元数据)、network(网络与会话)、operations(安装/卸载等操作)、req(需求解析与构建)、resolution(依赖解析,含 legacy 与 resolvelib 两条路径)、utils与vcs等模块;第三方依赖以 vendoring 方式固化在 src/pip/_vendor 中。注意,架构文档明确提示:pip 内部 API 不受支持,随时可能变化,因此以第三方方式直接 importpip._internal并不被鼓励。
AI 政策:LLM 工具的使用边界
pip 项目并不禁止贡献者使用 LLM 工具,但要求遵守专门的 AI_POLICY.md,其核心原则是:每一项贡献都必须由一位真正理解代码、拥有其版权并愿意为之负责的人类背书。具体包括:
- PR 中不得出现 LLM 机器人的
Co-authored-by:署名,带有 LLM 联合作者署名的 PR 会被直接关闭,因为这会危及项目的版权状态; - 提交 PR 即表示你承诺:你是作者或拥有合法的提交权利,理解提交的代码,并对它负全部责任——"这是 LLM 写的"不是对评审问题的合格回答;
- 禁止无监督的 agentic 工具(如自动批量提交 PR 的机器人账号);重复的低质量(slop)贡献会被关闭且不再评审,行为类似机器人的账号会被永久封禁;
- LLM 生成的评论必须简洁、准确,并随时准备好为之辩护;冗长、重复或离题的评论可能被标记为垃圾信息。
提交 Pull Request 的规范
目标分支与基本要求
- 所有 PR 都提交到
main分支,并附带清晰的描述(做了什么、为什么)。 - 你必须有法律上的许可来分发所贡献的代码,且代码必须可在 MIT License 下分发(LICENSE.txt)。
- 必须为改动提供测试,并先在本地运行测试。pip 官方支持多个 Python 版本与操作系统(见下文"自动化测试"),任何 PR 都必须考虑并兼容所有这些平台。
小而自洽:控制 PR 规模
评审质量会随补丁规模增大而下降,因此:
- PR 应当保持小、自洽、范围受限;一个大型功能往往需要拆成多个小 PR 分批落地;
- PR不应充当"功能分支",即不要在 PR 内部持续进行开发迭代,而应拆解成可独立评审、独立合并的小部分;
- 避免夹杂与本次改动无关的"外观性"修改(如重排注释/文档中的文本、增删空行或行内空白),这类清理可单独作为 "formatting cleanup" PR 提交。
注意:贡献者可以使用任何开发工具,但必须确保提交的代码满足项目要求,并且足够理解自己提交的代码以回应评审意见。
自动化测试与持续集成
所有 PR 以及对main分支的合并都会基于.github/workflows下的工作流文件在 GitHub Actions 上自动测试(详见 CI 文档)。你可以在 PR 页面看到 CI 运行状态与结果;若某个构建失败,可通过 "Details" 链接查看输出。需要重跑 CI 时,可关闭再重新打开 PR,或向 PR 追加一次提交;必要时维护者也可以手动重启某个 job/build。
测试矩阵
pip 的测试覆盖多种解释器、操作系统与架构(详见 CI 文档):
- 解释器:CPython 3.10、3.11、3.12、3.13、3.14、3.15,以及最新的 PyPy3(当前仓库 pyproject.toml 声明
requires-python = ">=3.10",__pip-runner__.py中另有镜像副本); - 操作系统:Linux、Windows、macOS;
- 架构:x64、x86、arm64(仅 macOS)。
CI 检查项
CI 运行的检查分为五类:
| 检查类型 | 内容 |
|---|---|
| lint | 由.pre-commit-config.yaml定义的代码风格检查 |
| docs | 文档构建检查 |
| vendoring | 校验 src/pip/_vendor 目录是否为干净的 vendored 状态 |
| unit | tests/unit 下的单元测试 |
| integration | 主要位于 tests/functional 的集成测试 |
| package | 打包步骤验证 |
其中 lint、docs、vendoring、package 只在 3 个操作系统的 x64 变体上运行即可;只有单元测试与集成测试需要覆盖全部解释器组合。
本地运行测试
开发环境搭建与测试执行细节见 Getting Started 文档。pip 的测试用 pytest 编写、由 nox 驱动,推荐并行运行以节省时间:
# 并行运行(推荐) $ nox -s test-3.10 -- -n auto # 顺序运行 $ nox -s test-3.10 # 指定解释器版本(如 3.15 或 pypy3) $ nox -s test-3.15nox 会将其余参数转发给 pytest,因此可以使用 pytest 的各种选择方式,例如按文件名、标记(-m unit)或关键字(-k "install and not wheel")挑选测试。相关测试工具依赖(pytest、pytest-xdist、virtualenv 等)定义在 pyproject.toml 的[dependency-groups] test中;pytest 的基础配置(如--disable-socket、--ignore=src/pip/_vendor等 addopts)也在同一文件中。
NEWS 条目:每个非平凡改动都要写变更日志
NEWS.rst文件由 towncrier 管理,所有非平凡的改动都必须附带一条 news entry。towncrier 的配置(条目目录、类型、渲染模板、issue 引用格式)集中在 pyproject.toml 的[tool.towncrier]段:条目目录为news/,输出文件为NEWS.rst,渲染模板为 tools/news/template.rst。
如何创建 NEWS 条目
- 先创建一个描述本次改动的 issue(PR 本身可以充当该 issue,但官方更推荐有独立 issue,例如 PR 因代码质量问题被拒时仍有据可查);
- 取该 issue/PR 的编号,在
news/目录下创建一个以编号命名、后缀为类型名的文件:news/<number>.<type>.rst。
例如,issue/PR 编号为1234且修复了一个 bug,则创建news/1234.bugfix.rst。一个 PR 可以跨越多个类别,比如同时新增功能并废弃旧功能,就同时创建news/NNNN.feature.rst与news/NNNN.removal.rst;若一个 PR 涉及多个 issue/PR,可为每个编号创建内容完全相同的文件,towncrier 会自动去重。
当前仓库 news/ 目录中即有真实示例:
- news/13084.bugfix.rst:修复 zipapp 场景下 pip 自身版本检查报告环境旧版本而非运行中版本的问题;
- news/14235.feature.rst:通过不再解析每条
PATH条目来加速安装带 console scripts 的 wheel; - news/14160.trivial.rst 与 news/14177.trivial.rst:trivial 类型条目(回归测试扩充等);
- news/certifi.vendor.rst、news/distlib.vendor.rst、news/msgpack.vendor.rst、news/packaging.vendor.rst、news/platformdirs.vendor.rst:vendor 类型条目,以库名作为文件名键。
条目内容规范
- 条目是 reStructuredText 格式的文本,渲染后作为
NEWS.rst中的条目正文;无需在正文里引用 issue/PR 编号,towncrier 渲染时会自动附上所有相关 issue 的引用(issue_format = "#{issue}"格式链接);文件末尾必须有一个换行。 - 风格要求:简洁、句子式大小写(sentence case)、少于 80 字符、祈使语气——一条合格的条目应当能补全句子 "This change will ..."。极少数单行不够的情况,可以用一行祈使语气摘要 + 空行 + 一到多段描述,每段按 80 字符换行。
- 记住:news 条目面向最终用户,只应包含对用户有意义的细节。
选择 NEWS 条目类型
towncrier 在 pyproject.toml 中定义了七类条目(渲染时按showcontent决定是否在NEWS.rst中展示内容,其中 Trivial Changes 不展示):
| 类型目录 | 在 NEWS.rst 中的分组 | 说明 |
|---|---|---|
removal | Deprecations and Removals | 弃用与移除 |
feature | Features | 新功能 |
bugfix | Bug Fixes | 缺陷修复 |
vendor | Vendored Libraries | vendored 库的升级/移除/新增 |
doc | Improved Documentation | 文档改进 |
process | Process | 流程、政策类变更(不常用,如版本方案变更、弃用政策更新) |
trivial | Trivial Changes(不展示内容) | 无需向用户播报的琐碎改动 |
trivial 变更指不值得进入 news 文件的改动,例如对公众无影响的代码重构、错别字修正、空白调整等。标记方法:在news/目录下添加一个随机命名的空文件,扩展名为.trivial.rst。POSIX 下可运行touch news/$(uuidgen).trivial.rst;Windows PowerShell 下可运行New-Item "news/$([guid]::NewGuid()).trivial.rst"。核心维护者也可以给 PR 添加 "skip news" 标签达到同样效果。
vendor 变更:升级、移除或新增一个 vendored 库,除了可能伴随的 feature/bugfix 等条目外,还需用news/<library>.vendor.rst文件单独提及;以库名为键,可避免同一库更新两次时产生重复条目。可见当前仓库的五个 vendor 条目正是这一规范的体现。
process 变更:涉及流程、政策或其他非代码类的显著变化,可使用news/<name>.process.rst,通常不常用。
保持分支同步:fetch + rebase 工作流
main分支更新频繁,工作期间至少需要同步一次。假设你的 Git 已配置好远程仓库,运行git remote -v的输出形如:
origin https://github.com/USERNAME/pip.git (fetch) origin https://github.com/USERNAME/pip.git (push) upstream https://github.com/pypa/pip.git (fetch) upstream https://github.com/pypa/pip.git (push)其中USERNAME是你的 GitHub 用户名,origin是你的 fork,upstream是 pip 主仓库。首先从主仓库拉取最新变更:
$ git fetch upstream更新本地main分支,并把上游变更 rebase 到其上:
$ git checkout main $ git rebase upstream/main此时可能需要解决合并冲突。解决后,将本地main推送到你的origin:
$ git checkout main $ git push origin main更新特性分支时流程类似:
$ git checkout awesome-feature $ git fetch upstream $ git rebase upstream/main良好实践是把工作分支及时推到origin备份(git push origin awesome-feature,该操作不会创建 PR)。分支再次需要更新时,由于远端已有同名分支,需强制推送:
$ git push -f origin awesome-feature-f/--force会用本地分支强制覆盖origin分支;若该分支上有打开的 PR,强制推送会更新该 PR(评审要求修改后非常有用)。若遇到如下报错,通常意味着分支落后于远端,重试push -f即可:
! [rejected] awesome-feature -> awesome-feature (non-fast-forward) error: failed to push some refs to 'https://github.com/USERNAME/pip.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Integrate the remote changes (e.g. hint: 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details.成为维护者
想成为正式维护者,先从小事做起:参与 issue 分类(triage)。维护者会为活跃一段时间(通常至少 2–3 个月)且做出积极贡献的贡献者开放 issue 分类权限,这是成为维护者的可选但强烈推荐的第一步。分类工作可参考 Issue Triage 指南,其中介绍了 issue 跟踪器的标签体系(C-类别、kind、OS-、project、resolution、state、type等前缀分类,以及good first issue、S: needs triage、skip news、needs rebase or merge等独立标签)和 issue 自动化流程(如新 issue 自动打S: needs triage标签、关闭 30 天后锁定线程等)。
当你认为准备好了(通常至少是开始分类 5 个月后),联系任意一位维护者,他们会启动现有维护者之间的投票。成为维护者后,通常会获得以下权限:
- GitHub Push 访问权限;
- PyPI 发布访问权限;
- CI 管理能力;
- ReadTheDocs 管理能力。
总结:一份高质量贡献的检查清单
- 通读 内部架构指南,理解改动涉及的核心模块(
src/pip/_internal); - 阅读并遵守 AI_POLICY.md,确保对每一行代码负责;
- 将改动拆成小且自洽的 PR,提交到
main分支,避免无关的外观性修改; - 补充测试并在本地用
nox -s test-3.10 -- -n auto等命令跑通(参考 Getting Started); - 为改动创建符合规范的 news/ 条目(非 trivial 必填);
- 用
git fetch upstream && git rebase upstream/main保持分支同步,必要时git push -f origin更新 PR; - 在 PR 中清晰描述做了什么与为什么,耐心回应评审意见。
感谢你的贡献!
- 包管理器
- 开发工具
【免费下载链接】pip
The Python package installer
相关推荐
HackRF贡献者指南:从Issue提交到Pull Request流程
HackRF贡献者指南:从Issue提交到Pull Request流程 作为开源软件无线电平台(Software Defined Radio, SDR)的领军项
嵌入式硬件开发固件通信贡献 pytest:从提交 Issue 到提交 Pull Request 的完整参与指南
贡献 pytest:从提交 Issue 到提交 Pull Request 的完整参与指南 本文基于 pytest 仓库的官方贡献文档( doc/en/contr
测试开发工具在 refine 管理后台做数据检索:全局防抖搜索与表格过滤的落地写法
在 refine 管理后台做数据检索:全局防抖搜索与表格过滤的落地写法 在 refine 搭建的管理后台里,数据检索卡慢,往往不是表格组件的问题,而是搜索请求在
前端企业应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考