From 608a79d48a957700d01f1fe3f057f485a445cc20 Mon Sep 17 00:00:00 2001 From: chengma Date: Thu, 23 Jul 2026 15:03:19 +0800 Subject: [PATCH] chore: pin NumPy 1.26.4 --- docs/03-tech-stack.md | 3 +- docs/packaging.md | 2 +- docs/tasks/T-699.md | 47 ++++++++++++++++++++++++++++ requirements.txt | 3 +- tests/test_dependency_constraints.py | 23 ++++++++++++++ 5 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 docs/tasks/T-699.md create mode 100644 tests/test_dependency_constraints.py diff --git a/docs/03-tech-stack.md b/docs/03-tech-stack.md index bbc34fb..586985b 100644 --- a/docs/03-tech-stack.md +++ b/docs/03-tech-stack.md @@ -81,7 +81,8 @@ set AUTO=1 && python prototypes/demo.py - 运行时第三方依赖统一写入根目录 `requirements.txt` 并锁定版本;换机或 CI 使用 `python -m pip install -r requirements.txt` 安装。 - 开发检查依赖写入 `requirements-dev.txt`;当前只包含 ruff,不属于运行时或打包依赖。 - 打包依赖只写入 `requirements-build.txt`;PyInstaller 不属于运行时依赖,不写进 `requirements.txt`。 -- 当前直接依赖锁定:PySide6 6.5.3、openpyxl 3.1.3、requests 2.31.0、websocket-client 1.6.1、Pillow 9.5.0。 +- 当前直接依赖锁定:PySide6 6.5.3、NumPy 1.26.4、openpyxl 3.1.3、requests 2.31.0、websocket-client 1.6.1、Pillow 9.5.0。 +- NumPy 1.26.4 是 PySide6/Shiboken 6.5.3 的二进制兼容约束。项目目前不直接调用 NumPy API,但不得让其他依赖把运行或打包环境升级到 NumPy 2.x,否则可能在 GUI 启动导入阶段触发 ABI 不兼容错误。 - 新增第三方依赖前,先在本文说明用途、替代方案和维护成本,并同步更新 `requirements.txt`。 - GUI 框架固定为 PySide6,不允许混入 Tkinter/PyQt/Web 形成两套 UI。 - 不引入第二套浏览器自动化方案(不要 `app/cdp.py` 之外再混入 selenium/playwright)。 diff --git a/docs/packaging.md b/docs/packaging.md index 6d89ab3..178f167 100644 --- a/docs/packaging.md +++ b/docs/packaging.md @@ -13,7 +13,7 @@ py -3.10 -m pip install -r requirements-build.txt ``` -`requirements-build.txt` 会先安装 `requirements.txt` 的运行依赖,再安装 PyInstaller。依赖必须安装到 Python 3.10 环境里,避免 PATH 上的 Python 3.7/3.12/3.14 打出不可比对的包。 +`requirements-build.txt` 会先安装 `requirements.txt` 的运行依赖,再安装 PyInstaller。依赖必须安装到 Python 3.10 环境里,避免 PATH 上的 Python 3.7/3.12/3.14 打出不可比对的包。运行依赖固定使用 NumPy 1.26.4,以兼容 PySide6/Shiboken 6.5.3;正式打包前不得单独升级到 NumPy 2.x。 ## 二、打包命令 diff --git a/docs/tasks/T-699.md b/docs/tasks/T-699.md new file mode 100644 index 0000000..7ce3e36 --- /dev/null +++ b/docs/tasks/T-699.md @@ -0,0 +1,47 @@ +--- +id: T-699 +title: 锁定 NumPy 1.26.4 兼容 PySide6 +phase: 7 +deps: [T-521, T-540] +status: DONE +created: 2026-07-23 +--- + +## 问题 / 背景 + +Python 3.10 环境中的 NumPy 曾被其他依赖升级到 2.2.6,而当前 PySide6/Shiboken 6.5.3 包含按 NumPy 1.x ABI 编译的模块。启动 GUI 时因此出现二进制兼容警告,存在导入失败或崩溃风险。 + +本地降级只能修复当前机器;如果项目依赖没有明确约束,换机安装、重新打包或安装其他依赖时仍可能再次升级到 NumPy 2.x。 + +## 方案 + +- 在根目录 `requirements.txt` 精确锁定 `numpy==1.26.4`。 +- `requirements-build.txt` 继续通过 `-r requirements.txt` 继承该约束,不重复维护第二份版本。 +- 在技术栈和打包文档说明该依赖属于 PySide6/Shiboken 6.5.3 的 ABI 兼容约束。 +- 增加纯逻辑回归测试,确保依赖文件只保留一条精确的 NumPy 版本约束。 + +## 验收要点 + +- `requirements.txt` 包含且仅包含 `numpy==1.26.4`。 +- Python 3.10 环境可正常导入 NumPy、Shiboken6 和 PySide6,不再出现 NumPy 2.x ABI 警告。 +- `pip check` 不报告依赖冲突。 +- 自动验证: + - `py -3.10 -m unittest tests.test_dependency_constraints` + - `py -3.10 -m unittest discover -s tests` + - `py -3.10 -m ruff check app tests main.py` + - `py -3.10 -m compileall app main.py` + - `git diff --check` + +## 边界(不改什么) + +- 不引入或恢复 OpenCV,不修改图片处理实现。 +- 不升级 PySide6/Shiboken,不调整 GUI、CDP、采集、生成或更新蝦皮流程。 +- 不修改用户数据、数据库 schema 或打包目录结构。 + +## 执行记录 + +- 2026-07-23:在 `requirements.txt` 增加 `numpy==1.26.4` 精确约束;`requirements-build.txt` 继续继承运行时依赖,不重复维护版本。 +- 技术栈和打包文档已明确该版本用于兼容 PySide6/Shiboken 6.5.3,禁止打包环境被其他依赖隐式升级到 NumPy 2.x。 +- 新增依赖约束回归测试,确保 `requirements.txt` 中只保留一条 `numpy==1.26.4`。 +- Python 3.10 环境验证通过:NumPy 1.26.4、PySide6 6.5.3 和 Shiboken6 可正常导入,`pip check` 未发现依赖冲突。 +- 验证通过:定向测试 1 项、`py -3.10 -m unittest discover -s tests`(684 项)、`py -3.10 -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`git diff --check`。 diff --git a/requirements.txt b/requirements.txt index 32d3ed8..2bb3d34 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ PySide6==6.5.3 +numpy==1.26.4 openpyxl==3.1.3 requests==2.31.0 websocket-client==1.6.1 -Pillow==9.5.0 \ No newline at end of file +Pillow==9.5.0 diff --git a/tests/test_dependency_constraints.py b/tests/test_dependency_constraints.py new file mode 100644 index 0000000..7f3d265 --- /dev/null +++ b/tests/test_dependency_constraints.py @@ -0,0 +1,23 @@ +from pathlib import Path +import unittest + + +PROJECT_ROOT = Path(__file__).resolve().parents[1] + + +class DependencyConstraintsTest(unittest.TestCase): + def test_numpy_is_pinned_to_compatible_version(self) -> None: + requirements = (PROJECT_ROOT / "requirements.txt").read_text( + encoding="utf-8" + ) + numpy_constraints = [ + line.strip() + for line in requirements.splitlines() + if line.strip().lower().startswith("numpy") + ] + + self.assertEqual(["numpy==1.26.4"], numpy_constraints) + + +if __name__ == "__main__": + unittest.main()