ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Kornia API 表面稳定性治理:Import Surface CI 检查如何审计公共导出移除

Kornia API 表面稳定性治理:Import Surface CI 检查如何审计公共导出移除 计算机视觉人工智能深度学习图像处理【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址https://gitcode.com/gh_mirrors/ko/kornia点击查看免费下载本指南围绕 Kornia 仓库中的Import SurfaceCI 检查展开讲解其如何基于 tests/api_surface.json 与 tests/api_surface_removals.json 两份记录文件审计每一次对公共 API 导出__all__中的名字的移除。读完本文你将掌握该检查的判定规则、合法移除的登记流程、底层导出解析器的实现原理以及它如何与 Kornia 的 API 稳定性政策docs/source/get-started/stability.rst配合防止公共符号在无感知的情况下被静默删除。一、为什么需要一个「导入表面」检查Kornia 拥有庞大的下游依赖群体且越来越多的大语言模型在训练语料中携带其 API 快照两者都会因为 API 的静默变动而受损。历史上发生过两次典型事故0.8.3 的kornia.utils清理一次发布直接移除了 34 个公共名字中的 20 个没有任何弃用窗口数月后才在一次审计中被发现——因为 CI 中没有任何环节将公共表面与上一版本做对比。kornia.geometry.transform.pyramid的pad泄漏issue #3986一个从未进入__all__的名字只因模块恰好以from torch.nn.functional import pad的形式导入而变得可导入后来的重构删除了该导入导致第三方from kornia.geometry.transform.pyramid import pad静默崩溃。这两类问题对应两种不同的「公共表面」文档化的导出列入__all__的名字属于稳定核心模块的正式公共 API未文档化的绑定模块顶层绑定的其他名字导入、赋值、定义虽然不在__all__中但同样可能被下游引用。Import Surface检查changelog 记录于 changelog.d/migration-086.fixed.md关联 PR #4190 与 #4230正是为同时覆盖这两类移除而设计。二、三层防线测试库存、静态检查与 CI 工作流整套机制由三层独立但互相配合的防线构成。2.1 第一层pytest 运行时库存守卫tests/test_api_surface.py 是运行时防线。它以 tests/api_surface.json 中记录的模块清单为参数化来源执行两类断言test_no_public_name_removed将当前库中每个模块的__all__与库存中记录的公开名字做差集任何被移除的名字都会使测试失败直到开发者在同一 PR 中更新库存。test_public_names_resolve遍历kornia包下所有声明了__all__的模块逐个用hasattr验证__all__中的名字确实绑定在模块上——因为test_no_public_name_removed对比的本身就是__all__如果一个名字的绑定被删除但还残留在__all__里前一个测试是看不见的。此外test_inventory_is_a_mapping_of_module_to_public_names守卫库存文件本身的形状如果某个模块的条目被改写成{}set(recorded) - current会空洞地通过从而让该模块在无人察觉的情况下失去保护。2.2 第二层基于 AST 的静态检查脚本.github/scripts/check_import_surface.py 是Import Surface检查的核心实现。它只使用ast静态比较从不导入 kornia 本身因此在无法构建/运行包的环境中也能工作。用法如下python3 .github/scripts/check_import_surface.py --base-ref origin/main退出码为 1 的情况包括从__all__中移除名字违反稳定性政策的文档化公共 API、删除tests/api_surface.json跟踪的模块、或本次变更中的移除记录与实际导出变化不匹配。具体来说脚本基于merge-base而非 base 分支尖端对比工作区与基础版本避免 PR 分支之后 base 分支前移导致误报测试见 tests/scripts/test_check_import_surface.py 中的test_main_uses_merge_base_not_tip_of_base_ref。2.3 第三层CI 工作流.github/workflows/import-surface.yml 将上述脚本接入 GitHub Actions作用于main分支的 PR路径过滤包括kornia/**/*.py任何库代码变更tests/api_surface.json与tests/api_surface_removals.json两个记录文件任一被触碰都会触发检查check_import_surface.py与工作流文件自身工作流显式设置fetch-depth: 0以获取 merge-base 提交然后执行- name: Check import surface run: python3 .github/scripts/check_import_surface.py --base-ref origin/${{ github.base_ref }}changelog 片断中「Both record files trigger the workflow」一句对应路径过滤中的两条api_surface*规则——因为检查会双向读取库存一条记录是逃生通道而删除某个模块的 key 本身就会致命。三、两份记录文件合法的移除如何被「登记」「记录在同一个变更中」是整套授权机制的基石。仓库维护着两份 JSON 记录文件3.1tests/api_surface.json稳定核心模块的公开名字库存该文件是dict[str, list[str]]结构每个 key 是一个稳定核心模块名value 是该模块的公开名字列表。例如 tests/api_surface.json 中记录了kornia.augmentation、kornia.geometry等模块下的公开类。它扮演两个角色作为test_no_public_name_removed的参数化来源任何从__all__移除的名字都必须先从库存中同步删除作为Import Surface检查认可的「确认」来源只有从该模块条目中删除同一个 module/name 对才算授权该移除。3.2tests/api_surface_removals.json库存之外的精确移除记录对于库存不覆盖的场景——子模块 API 只在祖先包下被记录、或 API 完全不在库存清单内——使用精确的 module/name 对登记文件中的真实示例为{ kornia.contrib: [ BoxMotTracker ], kornia.contrib.boxmot_tracker: [ BoxMotTracker ] }见 tests/api_surface_removals.json。这一设计解决了「祖先条目不能替代后代」的问题kornia.pkg从pkg.a重新导出的thing与pkg.b中同名但无关的符号必须精确区分——记录kornia.pkg失去thing并不能替kornia.pkg.b的移除背书测试见test_check_file_ancestor_entry_does_not_excuse_a_sibling_of_the_same_name。四、判定规则什么能授权、什么不能changelog 片断明确列举了不能授权移除的几种情况在脚本与测试中均有对应实现情况后果对应实现库存条目被改写成错误形状非字符串 key、非字符串列表等拒绝整份库存什么都不授权_parse_inventory对错误形状整体返回None测试test_inventory_removals_rejects_an_entry_whose_value_is_not_a_list删除库存中的模块 key检查本身致命失败untracked_modules测试test_untracked_modules_reports_a_deleted_key删除与本次__all__移除无关的名字无法授权test_check_file_recording_a_different_name_does_not_excuse_this_one与库代码无关的 Python 编辑未触碰任何kornia/文件无法作为移除证据test_main_fails_on_an_inventory_removal_this_change_does_not_make在更早的变更中预登记的确认不可复用removal_acknowledgements只计算本次新增的 module/name 对测试覆盖「staged in earlier changes」场景库存损坏缺失、无法解析、错误形状关闭一切逃生通道inventory_removals两端任一不可读即返回空映射反过来合法的登记方式是有库存条目的模块从tests/api_surface.json的对应条目中删除该名字保留模块 key必要时置为[]无库存条目的模块或 API向tests/api_surface_removals.json新增精确的 module/name 对。每条新登记的记录都必须匹配本次 diff 中一次真实的__all__移除「only new entries matching a current__all__removal count」。被授权移除的名字在 CI 输出中以::notice呈现未登记、未豁免的移除则以::error呈现并使检查失败。五、导出解析器静态证明「名字确实离开」changelog 片断提到「The export resolver includes implicit submodule bindings and rejects unsupported dynamic binding expressions as evidence of removal」对应脚本中的_ExportResolver类。它是一个刻意保持保守的小型解释器解决一个关键盲区通过from .sub import *重新导出的包如kornia.geometry、kornia.morphology没有可静态比较的__all__。解析器的工作方式仅跟随有序的模块级语句导入、赋值、定义与字面量__all__声明包含隐式子模块绑定在包内导入其子模块时子模块名会作为该包的绑定被计入bind_child逻辑因此删除一个from .sub import *重导出会被识别为导出表面变化拒绝动态绑定遇到调用、赋值表达式NamedExpr、含默认值/装饰器/注解的函数定义等无法静态确定对全局命名空间影响的语句将该模块标记为「未知」而未知表面永远不会被当作移除证据「unknown surface never proves that an inventory name was removed」。这一设计堵住了两条绕过路径把包内某个同名字符串的移除当作包级移除的证据祖先条目不能授权后代以及利用globals().update(...)之类的动态表达式伪造移除。六、三条豁免路径报告但不致命并非所有__all__移除都会导致检查失败。脚本明确列出三类豁免模块级__getattr__弃用垫片新版本中存在模块级__getattr__时推定其在以弃用垫片方式继续服务旧名字即kornia.utils的模式——移除被报告但非致命test_check_file_getattr_shim_is_not_fatalkornia.contrib实验层根据稳定性政策kornia.contrib属于「No stability promise」层级其移除只报告不失败test_check_file_contrib_removal_is_not_fatal本次变更中已登记的精确 module/name 移除。此外未文档化的绑定移除从未进入__all__的名字始终只是信息性报告——对它们硬失败会让所有偶然的第三方重导出变成永久 APItest_diff_surfaces_flags_undocumented_removal_separately。七、实操为一次合法的公共 API 移除登记结合稳定性政策文档docs/source/get-started/stability.rst中的「Recording a completed deprecation」一节一次合规的移除流程是先弃用公共符号至少先在一个 minor 版本中以kornia.core._compat.deprecated包裹保留旧调用并发出DeprecationWarning等待窗口结束后移除 API并在changelog.d/PR.breaking.md中记录该破坏性变更同步更新库存从tests/api_surface.json对应条目删除该名字保留模块 key若模块无库存条目或只记录在祖先包下则在tests/api_surface_removals.json登记精确的 module/name 对本地验证推送前运行python3 .github/scripts/check_import_surface.py --base-ref origin/main确认输出为::notice而非::error同时运行pytest tests/test_api_surface.py确认库存守卫通过若需重新生成库存快照例如新增公共 API可运行python3 tests/test_api_surface.py触发其regenerate()路径。需要特别注意登记必须与移除发生在同一个变更中。在单独 PR 中预登记、或者删掉模块 key 让模块整体失去保护都会被检查拒绝——前者是「acknowledgements staged in earlier changes cannot authorize removals」后者是「dropping the key ends that guard silently」。八、与其他保障的关系弃用窗口与发布说明仍然适用changelog 片断最后强调「Deprecation windows and release notes still apply」。Import Surface检查只是执行机制不是政策豁免稳定性政策的三条核心承诺依然有效移除前至少一个 minor 版本的弃用窗口、禁止静默改变语义、发布说明必须列出稳定核心的每一次弃用/移除/行为变更修正明确错误错误数学、与文档约定不符或安全问题的变更可走「逃生舱口」免于弃用窗口但发布说明必须显式声明库存编辑是「政策合规移除」的确认而不是替代政策本身——这正是检查脚本与测试反复强调的test_check_file_inventory_removal_is_not_fatal中跟随test_no_public_name_removed错误信息指引完成登记的贡献者检查必须识别该编辑而非硬性失败。九、小结Kornia 的Import Surface检查changelog 片断 changelog.d/migration-086.fixed.md把「公共 API 不得静默消失」从口头约定变成了三层可执行的防线运行时 pytest 库存守卫、静态 AST 导出比对、CI 工作流兜底。两份记录文件分别覆盖稳定核心模块与库存外 API 的精确登记_ExportResolver用保守的静态解释补上了通配符重导出包这一盲区而所有豁免路径都确保「报告但非致命」的边界清晰。对于 Kornia 的维护者这意味着每一次移除都必须在同一 PR 中留下明确记录并经过审查时刻对于下游用户与依赖 Kornia API 的 LLM 快照这意味着公共表面有了可审计、可追溯的变更台账。赞分享计算机视觉人工智能深度学习图像处理【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址https://gitcode.com/gh_mirrors/ko/kornia点击查看免费下载相关推荐Kornia Import Surface 检查机制公开 API 移除的精确授权与 CI 守卫解析Kornia Import Surface 检查机制公开 API 移除的精确授权与 CI 守卫解析 导读 本文围绕 Kornia 仓库中 changelog.计算机视觉深度学习人工智能图像处理NemoClaw PR Comparator 的 Tier 2 代码质量检查描述漂移、迁移完整性、公共表面与根因治理NemoClaw PR Comparator 的 Tier 2 代码质量检查描述漂移、迁移完整性、公共表面与根因治理 NemoClaw 仓库维护了一套基于 ASlate v2 公共 API 表面一致性校准Public-Surface Reconciliation实战指南Slate v2 公共 API 表面一致性校准Public Surface Reconciliation实战指南 导读 本文以 Plate 仓库中的 202前端富文本UI组件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表