Skip to content

Code Analysis SymPy

Tu Shaokun edited this page Nov 6, 2026 · 2 revisions

SymPy 1.14 的全库覆盖和同名导出

固定源码为 16fa8553,分析根目录是整个 SymPy 仓库。先核对已有调用方和 Python 实际导入的对象,再用 Code Analysis 检查文件和函数证据。

一张多项式表会中断整库分析

公开 Labs bf0a29e7 在 Python 3.13 默认递归限制下退出 2,未生成原始事实。Python 成功解析了所有源码。触发错误的是一张 456 行的 Galois 预解式查找表,二元算式让 AST 深度达到 569。导入访问器在遍历操作数时耗尽了调用栈。只排除这一份文件,原版即可完成其他 1,571 个 Python 文件的分析。生成的查找表 · 加载查找表的位置

Draft #1217(5eb24a20e) 用显式栈按原顺序访问二元算式的操作数。保留该表并使用默认递归设置,CLI 完成了 1,572 个文件、30,355 条导入和 35,799 条函数记录,解析错误为 0。为核对原有分析语义,另在临时进程将递归上限设为 4,000,运行原版提取器。所得全库原始事实与候选版逐字节相同,解包后的 CLI 也得到相同结果。229 个模块测试通过。这份 PR 直接基于 Labs。上述数字属于固定版本,不代表其他表达式形状或任意项目都能完成。整库扫描修复 #1217

文件依赖能否说明导入的对象?

SymPy 的测试在第 2 行写 from sympy import Symbol, simplify,第 20 行把 simplify 当函数调用。顶层初始化文件从子包导出同名函数,子包再从实现模块导出它。公开 Labs 在排除查找表后的运行和 Draft #1217 的全库运行,都把这个名字记录为指向 sympy/simplify/__init__.py 的文件依赖,导入名显示为 *。这个文件确实参与加载。用 Python 比较对象身份,两个位置导入的都是 sympy/simplify/simplify.py:435 的同一个函数。真实调用方 · 顶层导出 · 函数实现

  • 在仓库的 sympy/ 目录按 Python AST 核对,8 处从 sympy 导入 simplify,另有 27 处从 sympy.simplify 导入它。两组的文件边均可指向加载路径,* 本身不能判断导入的对象能否调用。
  • 对照例 from sympy import abc 导入的确实是模块 sympy/abc.py。另一个固定源码小样本只改变运行时配置,同一条导入就能分别取得函数和模块。调查时先打开包的导出语句,有可运行环境再验证实际对象。这轮没有为同名文件增加通用的调用目标推断。
在固定 SymPy 源码上复核函数身份、公开 Labs 的错误和 Draft #1217 的全库结果

以下在临时目录运行。Python 环境只为这次检查安装 SymPy 声明的依赖 mpmath,SymPy 直接从指定 Git 提交加载。默认运行固定的 Labs 版本,预期退出码为 2。复核 Draft #1217 时,先执行 export ARCHIFY_REF=5eb24a20e2961faa559ba083ea223b6b172f95ed,预期退出码为 0。

set -eu
w=$(mktemp -d)
pin() {
  git init -q "$w/$1"
  git -C "$w/$1" remote add origin "https://github.com/$2.git"
  git -C "$w/$1" fetch -q --depth=1 origin "$3"
  git -C "$w/$1" checkout -q --detach FETCH_HEAD
}
pin sympy sympy/sympy 16fa855354eb7bcabd3fe10993841e03b1382692
pin archify tt-a1i/archify "${ARCHIFY_REF:-bf0a29e7664f52973d06a8e6a608df2db1ecbd39}"
python3.13 -m venv "$w/env"
"$w/env/bin/python" -m pip -q install --disable-pip-version-check 'mpmath==1.3.0'
"$w/env/bin/python" -I -B - "$w/sympy" <<'PYCODE'
import importlib
from pathlib import Path
import sys

root = Path(sys.argv[1]).resolve()
sys.path.insert(0, str(root))
from sympy import Symbol, abc, simplify
from sympy.simplify import simplify as inner
assert simplify is inner is importlib.import_module("sympy.simplify.simplify").simplify
assert simplify is not importlib.import_module("sympy.simplify")
assert abc is importlib.import_module("sympy.abc")
print(Path(simplify.__code__.co_filename).relative_to(root), simplify.__code__.co_firstlineno)
x = Symbol("x")
print(simplify((x + 1)**2 - x**2))
PYCODE
(cd "$w/archify/archify/modules/code-analysis" && npm ci --ignore-scripts --no-audit --no-fund)
rc=0
BAUIFY_PYTHON="$(command -v python3.13)" node "$w/archify/archify/bin/archify.mjs" code-analysis check "$w/sympy" --language py --fail-on never --json --out "$w/facts" > "$w/receipt.json" || rc=$?
python3.13 - "$w" "$rc" <<'PYCODE'
import hashlib, json, sys
from pathlib import Path

root, rc = Path(sys.argv[1]), int(sys.argv[2])
print("exit", rc)
if rc == 0:
    data = (root / "facts" / "raw-facts.json").read_bytes()
    facts = json.loads(data)
    print(len(facts["files"]), "files,", len(facts["imports"]), "imports,",
          len(facts["functions"]), "functions,", len(facts.get("parse_errors", [])), "parse errors")
    print("sha256", hashlib.sha256(data).hexdigest())
else:
    error = json.loads((root / "receipt.json").read_text())["diagnostics"][0]
    print(error["code"], error["evidence"]["stderr"][-1])
PYCODE

返回团队验证记录

Clone this wiki locally