审查方式:基于 PR diff 静态分析(仓库本地已克隆,已核对引用关系) 注:
ghCLI 未登录 GitHub,本报告未发布为 PR 评论。如需发布,请先gh auth login。
| 项 | 内容 |
|---|---|
| 标题 | Fix compatibility check import side effects |
| 作者 | @echo-wee |
| 源分支 | echo-wee:fix-compatibility-mark-file-import |
| 目标分支 | CoderWanFeng:develop |
| 变更文件 | 2 个(office/compatibility.py、tests/test_code/test_optional_imports.py) |
| 提交数 | 1 |
| 摘要 | ① 保护首次运行标记文件写入,避免 HOME 不可写时 import 崩溃;② 移除模块级兼容性检查以消除 import-time 副作用;③ 新增不可写场景的回归测试 |
fix compatibility check import side effects(1 commit,含compatibility.py+ 测试 2 文件改动)
| 文件 | 类型 | 关键改动 |
|---|---|---|
office/compatibility.py |
修改 | _check_first_run() 包 try/except OSError;删除模块级 compatibility_checker = check_compatibility();补文件结尾换行 |
tests/test_code/test_optional_imports.py |
修改 | 新增 test_compatibility_check_does_not_fail_when_mark_file_cannot_be_written |
文件:office/compatibility.py(方法 _check_first_run,约 24–38 行)
改动将 mkdir / write_text 包进 try/except OSError:
try:
self.mark_file.parent.mkdir(exist_ok=True)
if not self.mark_file.exists():
self.mark_file.write_text(f"First run on {platform.system()} at {platform.platform()}")
return True
except OSError:
# 兼容性提示不应影响主包导入;HOME 只读或不可写时跳过首次运行提示。
return False
return FalsePermissionError是OSError子类,捕获范围正确;降级返回False(当作非首次运行,静默跳过警告),不会阻断import office。- 评价:核心修复有效。因为真实调用路径是
office/__init__.py:5→check_compatibility()→CrossPlatformCompatibility().__init__→_check_first_run(),此保护对import office同样生效。
文件:office/__init__.py:5 + office/compatibility.py:239
PR 摘要称 "Remove module-level compatibility checking to avoid import-time side effects",但本地核对发现:
office/__init__.py:5仍然存在compatibility_checker = check_compatibility()。check_compatibility()(compatibility.py:227)会:CrossPlatformCompatibility()(写标记文件)+display_warning()(非 Windows 首次运行时打印 rich 表格)。
因此本次删除的只是 compatibility.py 自身的重复模块级调用(即 ISSUES_AUDIT.md:221 记录的"双重 rich 表格输出" bug 的第二次触发),import office 的 import-time 副作用(写 ~/.python-office/first_run_mark + 显示警告)在 __init__.py:5 仍保留。
影响:
- 若目标仅是"修复 import 崩溃 + 去重",本 PR 已达成。
- 若目标是"让
import office完全无副作用",则未达成——__init__.py:5仍在 import 时写文件并可能打印。
建议:
- 在 PR 描述中澄清实际范围(消除
compatibility.py的重复模块级检查,而非完全移除 import 副作用);或 - 若确实要彻底无副作用,应同时移除
office/__init__.py:5的compatibility_checker = check_compatibility(),改为延迟/按需调用(例如首次调用具体 API 时再检查)。
compatibility.py结尾换行:diff 补了缺失的\n(\ No newline at end of file→ 加换行),符合 POSIX 文本规范,👍。build/lib/构建产物:仓库中存在build/lib/office/compatibility.py与build/lib/office/__init__.py旧版副本(仍含模块级调用),属 setuptools 构建遗留物,不应纳入版本库。建议加入.gitignore或清理,避免与源码混淆。
ISSUES_AUDIT.md:221记录了"双重 rich 表格输出"bug,本 PR 已修复该重复触发,建议在该审计文档中标注"已修复(PR #162)",避免后续复测重复扣分。
新增测试:test_compatibility_check_does_not_fail_when_mark_file_cannot_be_written
def test_compatibility_check_does_not_fail_when_mark_file_cannot_be_written(self):
with self._optional_import_test_environment():
compatibility = importlib.import_module("office.compatibility")
with mock.patch.object(compatibility.Path, "mkdir", side_effect=PermissionError("readonly")):
checker = compatibility.CrossPlatformCompatibility()
self.assertFalse(checker.is_first_run)- 验证了
mkdir抛PermissionError时实例化不崩溃且is_first_run == False,命中except OSError分支。✅ - 覆盖缺口:测试直接
import office.compatibility并实例化CrossPlatformCompatibility,未覆盖真实的import office端到端路径(即__init__.py:5→check_compatibility()→display_warning())。由于逻辑等价(都走_check_first_run),风险低,但建议补充一条import office在不可写场景下的冒烟测试,以锁住回归。
- 无硬编码凭据 / 密钥泄露 ✅
- 无
panic()/os._exit()/process.exit()等高危调用 ✅ print()仅出现在if __name__ == "__main__":测试块(compatibility.py:244-250),非生产路径 ✅
理由:改动方向正确、核心修复(_check_first_run 的 OSError 保护)真实有效且安全,回归测试到位;但 PR 描述与实际生效范围存在偏差——真正的 import-time 副作用入口 office/__init__.py:5 未被触及。建议合入前:
- 澄清/对齐描述:将"remove module-level compatibility checking to avoid import-time side effects"修正为"移除
compatibility.py的重复模块级检查(消除双重提示),并保护标记文件写入"; - (可选)彻底去副作用:若项目确实要求
import office零副作用,进一步移除office/__init__.py:5并改为延迟调用; - 补充
import office端到端不可写冒烟测试; - 仓库卫生:清理
build/lib/构建产物、更新ISSUES_AUDIT.md标注。
优先级排序:① 描述澄清(必须,避免误解)→ ② 端到端测试(建议)→ ③ 彻底去副作用 / 仓库卫生(可选,后续跟进)。
生成时间:2026-08-04 | 审查人:PR 代码审查专家(本地静态分析,未发布 GitHub 评论)