ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

pip 的 towncrier 变更日志模板解析:从 news fragment 到 NEWS.rst 的渲染机制

pip 的 towncrier 变更日志模板解析:从 news fragment 到 NEWS.rst 的渲染机制 包管理器开发工具【免费下载链接】pipThe Python package installer项目地址https://gitcode.com/gh_mirrors/pi/pip点击查看免费下载本篇技术指南围绕 pip 仓库中维护变更日志的核心模板文件 tools/news/template.rst 展开系统讲解 pip 如何基于 towncrier 将散落在news/目录的 news fragment 自动聚合、渲染为结构化的 NEWS.rst 变更日志并同步到 docs/html/news.rst 在线文档。读完本文你将掌握 pip 的 news 条目命名规范、[tool.towncrier]配置含义、该自定义 Jinja 模板每一段逻辑的作用以及发布流程中towncrier build的执行位置从而能独立为 pip 贡献 news 条目、理解其变更日志生成链路。一、背景为什么 pip 需要定制 towncrier 模板towncrier 是 Twisted 社区开发的经典变更日志聚合工具开发者将每个改动写成一个小文件news fragment发布时由工具按版本号收集并合并为一份完整的NEWS.rst。pip 在此基础上做了深度定制——它不只是使用默认模板而是维护了一份重度定制heavily customised的版本 tools/news/template.rst原因有两个在线文档的无缝集成pip 的在线文档通过sphinxcontrib.towncrier扩展渲染未发布的 news 条目见 docs/html/news.rst 第 10 行的.. towncrier-draft-entries:: Not yet released指令。避免空渲染当没有待渲染的 news 条目时该 Sphinx 扩展依然会触发模板渲染导致出现空白或错误的输出。模板开头的{% if sections[] %}守卫正是为此设计——它让整个渲染过程在没有条目可展示时直接跳过充当兼容性 hack模板注释明确说明This serves as a compatibility hack。从仓库的架构文档 docs/html/development/architecture/anatomy.rst 中也可以印证news/目录用于存放 news fragment每次 pip 产生对用户可见的变更都会在其中添加一个文件通常是一段指向 GitHub issue 的简短说明并在发布时通过 towncrier 自动化生成 NEWS 文件并自动删除旧条目而tools/news/template.rst正是towncrier 使用的 changelog 模板是一份 Jinja 文件。二、配置侧[tool.towncrier]与 news fragment 规范2.1 pyproject.toml 中的 towncrier 配置模板本身不孤立工作它与 pyproject.toml 第 132–154 行的[tool.towncrier]配置段紧密耦合[tool.towncrier] # For finding the __version__ package pip package_dir src # For writing into the correct file filename NEWS.rst # For finding the news fragments directory news/ # For rendering properly for this project issue_format #{issue} https://github.com/pypa/pip/issues/{issue}_ template tools/news/template.rst # Grouping of entries, within our changelog type [ { name Deprecations and Removals, directory removal, showcontent true }, { name Features, directory feature, showcontent true }, { name Bug Fixes, directory bugfix, showcontent true }, { name Vendored Libraries, directory vendor, showcontent true }, { name Improved Documentation, directory doc, showcontent true }, { name Process, directory process, showcontent true }, { name Trivial Changes, directory trivial, showcontent false }, ]逐项解读配置键取值以当前仓库为准作用package/package_dirpip/src定位包版本号src/pip/__init__.py中的__version__用于生成版本 (日期)标题filenameNEWS.rsttowncrier build 后写入的变更日志文件路径仓库根目录的 NEWS.rstdirectorynews/news fragment 的存放目录issue_format#{issue} https://github.com/pypa/pip/issues/{issue}_条目末尾 issue/PR 引用的 RST 链接格式templatetools/news/template.rst指定自定义渲染模板即本文主角type7 种类型定义条目分类removal、feature、bugfix、vendor、doc、process、trivialtype列表中有两个关键属性name渲染到 NEWS 中的小节标题如 Bug Fixes、Features模板通过definitions[type_][name]读取showcontent是否展示该类型的具体条目内容。trivial类型为false这与贡献指南中trivial 变更不值得出现在 news 文件中的定位一致——只有显示showcontent true的类型会渲染条目正文。模板第 27 行{% for type_ in definitions if (sections[section_name][type_] and definitions[type_][showcontent]) %}正是读取definitions即 pyproject.toml 的type列表来过滤有条目且允许展示内容的类型。2.2 news fragment 的命名与内容规范贡献者在提交非 trivial改动时必须附带 news 条目规范详见 docs/html/development/contributing.rst 的 NEWS Entries 章节命名规则以 issue/PR 编号 类型后缀命名如修复 bug 且编号为 1234则创建news/1234.bugfix.rst一个 PR 可跨多个类别创建多个文件如同时有news/NNNN.feature.rst与news/NNNN.removal.rst。去重机制若一个 PR 涉及多个 issue可为每个编号创建内容完全相同的文件towncrier 渲染时会自动去重模板第 33 行对issue_reference做了|sort后join(, )多个引用会合并到一条目上。内容风格条目内容是 reStructuredText 文本不需要在正文中自行引用 issue/PR 编号——towncrier 会自动附加引用。官方要求条目保持句子大小写sentence case、少于 80 字符、使用祈使语气应能补全句子 This change will ...内容面向最终用户只保留与用户相关的细节文件末尾必须有换行符。trivial 标记不需要进入 news 的改动纯重构、拼写修正、空白调整等可在news/目录添加一个随机命名、内容为空的.trivial.rst文件。POSIX 下可用touch news/$(uuidgen).trivial.rstWindows 下用New-Item news/$([guid]::NewGuid()).trivial.rst。注意trivial的showcontent false因此这些空文件不会出现在最终 NEWS 中。仓库现有 fragment 恰好展示了这几种类型例如 news/13084.bugfix.rstzipapp 场景下自检版本报告不正确的 bug 修复、news/14235.feature.rst、news/14160.trivial.rst自我引用 extras 回归测试扩展、以及*.vendor.rst系列certifi、distlib、msgpack 等依赖升级。三、模板逐段解剖渲染逻辑全解析完整模板仅 44 行tools/news/template.rst自上而下可拆为五个逻辑块。下面结合 Jinja 语法与 towncrier 数据模型逐段说明。3.1 空渲染守卫{% if sections[] %}第 10 行{% if sections[] %} ... {% endif -%}这是模板最关键的自定义点。towncrier 渲染时提供sections变量——一个以 section 名为键的字典其中空字符串对应默认 sectionpip 未使用 towncrier 的命名 sections 功能因此所有条目都在之下。当没有任何条目时sections[]为空整个渲染被跳过。这正是为sphinxcontrib.towncrier在无条目时也会触发渲染的问题而设的兼容性 hack模板第 3–9 行注释说明了这一点。3.2 版本标题行第 12–14 行{{ versiondata.version }} ({{ versiondata.date }}) {{ top_underline * ((versiondata.version versiondata.date)|length 3) }}versiondata.version和versiondata.date分别来自towncrier build --version传入的版本号与构建日期第二行用top_underline默认字符重复版本号 日期总长度加 3 次生成 RST 节标题下划线。对照 NEWS.rst 的实际输出26.2.1 (2026-08-04) 版本号长度 7、日期长度 10下划线长度恰好为(7 10) 3 20与模板算式一致。3.3 section 遍历第 25 行{% for section_name, entries_by_type in sections.items() -%}模板注释明确说明由于 towncrier 未公开的 sections 特性参见 twisted/towncrier#61该循环对section_name 恰好执行一次。pip 不使用命名 sections因此模板不会渲染 section 标题如 Features 这类标题是类型标题不是 section 标题。3.4 类型小节标题与条目渲染第 27–41 行{% for type_ in definitions if (sections[section_name][type_] and definitions[type_][showcontent]) %} {{ definitions[type_][name] }} {{ underlines[0] * definitions[type_][name]|length }} {% for message, issue_reference in sections[section_name][type_]|dictsort(byvalue) %} - {{ message }} {%- if type_ not in [vendor, process] %} ({{ issue_reference|sort|join(, ) }}){% endif %} {% endfor %} {% else %} No significant changes. {% endfor -%}类型过滤definitions即 pyproject.toml 的type列表。只有当前 section 下存在条目且showcontent为 true的类型才会渲染且顺序遵循 pyproject.toml 中的声明顺序removal → feature → bugfix → vendor → doc → processtrivial 因showcontentfalse永远被跳过。标题与下划线类型名如 Bug Fixes作小节标题underlines[0]默认-按标题长度生成下划线。条目内容sections[section_name][type_]是消息 → issue 引用列表的映射经dictsort(byvalue)按值排序保证输出稳定message即 fragment 文件内容。引用附加规则默认所有类型都会在条目后追加(issue#1, issue#2)形式的引用来源为issue_format配置但模板对vendor与process两种类型跳过引用第 36 行{%- if type_ not in [vendor, process] %}。这与实际输出吻合在 NEWS.rst 中Vendored Libraries 小节如 Upgrade certifi to 2026.6.17与 Process 小节如 Include a CycloneDX SBOM ...的条目不带(#xxx)引用而 Bug Fixes / Features 的条目几乎都带。空类型兜底若某版本没有任何showcontenttrue的条目模板输出 No significant changes.第 41 行。例如 NEWS.rst 中24.1 (2024-06-20)只包含 Vendored Libraries 小节而像23.3.2这样只有 Bug Fixes 的版本则正常渲染对应小节。3.5 Jinja 语法细节模板使用{%-/-%}形式的空白控制符精确裁剪换行与缩进保证渲染出的 RST 文件中条目以-列表项格式连续排列、不引入多余空行——这在 NEWS.rst 的输出中可以看到效果每个条目都是紧凑的单行- xxx (#14227)格式。四、实际应用渲染链路与发布流程4.1 本地验证与文档集成towncrier 的官方用法是在发布时执行towncrier build --version X.Y.Z --yes。pip 将渲染结果写入 NEWS.rst其文件头有一段明确的提示见 NEWS.rst 第 1–10 行.. note You should *NOT* be adding new change log entries to this file, this file is managed by towncrier. You *may* edit previous change logs to fix problems like typo corrections or such.即开发者不应手工修改 NEWS.rst 的主体内容该文件由 towncrier 全权管理。与此同时在线文档 docs/html/news.rst 通过.. towncrier-draft-entries:: Not yet released渲染未发布的草稿条目再通过.. pip-news-include:: ../../NEWS.rst引入已发布的完整历史。文档构建侧docs/html/conf.py的配置与之配套towncrier_draft_autoversion_mode: draft towncrier_draft_include_empty: True towncrier_draft_working_directory: pathlib.Path(docs_dir).parentautoversion_mode draft文档渲染时自动把未发布条目归入 Not yet released 草稿版本include_empty True即使没有草稿条目也渲染这正是模板空渲染守卫存在的原因——两者配合避免输出异常working_directory docs_dir.parent指向仓库根目录使sphinxcontrib.towncrier能正确找到tools/news/template.rst与news/目录。4.2 发布环节的调用位置在 pip 的发布自动化脚本 tools/release/init.py 的generate_news函数中可以看到实际调用def generate_news(session: Session, version: str) - None: session.install(towncrier) session.run(towncrier, build, --yes, --version, version, silentTrue)发布时通过 nox 会话nox -s release传入版本参数版本合法性由 tools/release/check_version.py 校验安装 towncrier 并执行towncrier build --yes --version 版本号。--yes表示自动删除已被合并进 NEWS 的 fragment 文件——这正是 docs/html/development/architecture/anatomy.rst 所述每次发布维护者会删除 news/ 中的旧文件的实现机制。4.3 依赖版本约束仓库在 pyproject.toml 第 96–103 行对 towncrier 相关依赖做了版本锁定# currently incompatible with sphinxcontrib-towncrier # https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/92 towncrier 24, sphinxcontrib-towncrier 0.2.0a0,注释明确由于sphinxcontrib-towncrier与新版不兼容towncrier必须被限制在 24。这解释了为何文档构建与发布自动化要配套固定版本——模板渲染行为会随 towncrier 主版本变化版本锁定保证tools/news/template.rst所用数据模型sections、definitions、versiondata、top_underline、underlines的稳定性。五、模板与 NEWS.rst 输出的对照验证以下用当前仓库真实数据验证模板每个渲染点1. 标题行公式对应 3.2 节26.2.1 (2026-08-04) 2. 类型小节与引用规则对应 3.4 节取自 NEWS.rst 的 26.2 版本Bug Fixes --------- - Only emit the invalid-metadata warning once per location per run, instead of repeating it during the same command. (#11436 https://github.com/pypa/pip/issues/11436_) - Handle BrokenPipeError when pip output is piped to a command that closes early. (#11608 https://github.com/pypa/pip/issues/11608_)Bug Fixes 小节标题以-下划线underlines[0]每条带(#11436)、(#11608)引用由issue_formatissue_reference|sort|join(, )生成。3. vendor 类型无引用对应 3.4 节跳过规则Vendored Libraries ------------------ - Upgrade certifi to 2026.6.17 - Upgrade distlib to 0.4.2 - Upgrade idna to 3.18与 Bug Fixes 不同这里没有(#xxx)后缀因为type_为vendor。4. Process 类型同样无引用Process ------- - Include a CycloneDX SBOM (Software Bill of Materials) file alongside vendored libraries.5. 空输出守卫对应 3.1 节当前news/目录中除*.vendor.rst与*.trivial.rst外还有若干未发布条目当某一版本只有trivial条目showcontentfalse而没有其他类型时模板会走{% else %}分支输出 No significant changes.且若sections[]为空则整个文件不渲染任何内容。六、给贡献者与维护者的实用要点新增条目三步在 GitHub 创建 issue/PR 获取编号 → 在 news/ 目录创建news/编号.类型.rst→ 写入不超过 80 字符、祈使语气、句子大小写的 RST 文本末尾留空行。类型可选removal、feature、bugfix、vendor、doc、process、trivial与 pyproject.toml 的type定义一一对应。不要手改 NEWS.rst文件头注释明确要求不得新增条目只能修正历史记录的拼写错误等。调试渲染本地可用towncrier build --version X.Y.Z --draft类草稿模式查看渲染效果发布脚本实际使用--yes直接消费并删除 fragment文档预览则依赖sphinxcontrib.towncrier的草稿渲染配合towncrier 24的版本约束使用。理解模板的两处定制核心一是{% if sections[] %}空守卫为 Sphinx 集成服务二是vendor/process不追加 issue 引用的规则——这两点是 pip 的 NEWS.rst 与 towncrier 默认输出最大的不同。相关文件速查tools/news/template.rst本文核心——pip 自定义的 towncrier 渲染模板pyproject.toml 第 132–154 行[tool.towncrier]配置类型定义、文件名、issue 引用格式、模板路径NEWS.rsttowncrier 生成的历史变更日志docs/html/news.rst在线文档接入点草稿渲染 历史引入docs/html/conf.py 第 83–88 行towncrier_draft_*文档构建选项docs/html/development/contributing.rst 第 75–129 行NEWS 条目编写规范与类型选择指南tools/release/init.py 第 119–121 行发布流程中的towncrier build调用news/news fragment 实际存放目录含*.bugfix.rst、*.feature.rst、*.trivial.rst、*.vendor.rst等示例赞分享包管理器开发工具【免费下载链接】pipThe Python package installer项目地址https://gitcode.com/gh_mirrors/pi/pip点击查看免费下载相关推荐Pipenv 的 towncrier 变更日志模板解析从 news 片段到 CHANGELOG.md 的自动化渲染机制Pipenv 的 towncrier 变更日志模板解析从 news 片段到 CHANGELOG.md 的自动化渲染机制 本篇技术指南聚焦 Pipenv 仓库中开发工具CLI包管理器PyInstaller 的 Changelog 管理机制基于 towncrier 的 News Fragment 工作流与 _template.rst 模板渲染详解PyInstaller 的 Changelog 管理机制基于 towncrier 的 News Fragment 工作流与 _template.rst 模板渲开发工具构建工具pip Changelog更新日志指南读懂 NEWS.rst 与 news 片段的工作机制pip Changelog更新日志指南读懂 NEWS.rst 与 news 片段的工作机制 pip 是 Python 生态中最核心的包安装工具本仓库即其包管理器开发工具上一篇抖音无水印下载没你想的那么难开源工具 douyin-downloader 从零上手指南下一篇绕过TPM升级Windows 11一个免费脚本让老电脑顺利上车创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表