feat/export-service
main
函数图像静态渲染(Function Plot)与导出服务(Markdown → HTML)的复审修复。本 PR 是 #28 审阅结论(2 P2 + 1 P3)修复后的复审提交。
#28
ast
RecursionError
nan
_polyline
docs/contracts/第二阶段接口契约-开发版.md
function-plot
backend 全量 pytest:621 passed(新增 5 项边界回归:超深表达式、超量节点、HTML 深表达式回退、极端 domain/range 无 nan/inf)。
backend
pytest
backend/
实现 Export Service 完整生命周期:mistune AST → Document AST → HtmlExporter 渲染完整 HTML5,异步任务注册表 + 取消 + 24h 产物过期。新增 5 个 /api/exports 端点与 15 项测试;pdf/docx 与函数图像静态渲染留待后续 PR。
- P1 链接/图片 URL 协议白名单校验,危险协议降级为纯文本 + warning - P2 图片 AST 字段映射(src=attrs.url,alt 取 children 文本) - P2 原始 HTML 块转义保留,正文不丢失 + warning - P2 过期/淘汰/重启清理导出产物文件 - P2 解析与渲染移入 asyncio.to_thread,运行中取消生效 - P2 function-plot 围栏别名补全 - 回归测试覆盖全部修复 Co-Authored-By: Claude Code <noreply@anthropic.com>
- 新增 app/plot 包:白名单表达式解析(ast 无 eval)+ FunctionPlot 模型 + 静态 SVG 渲染 - HtmlExporter 的 function_plot 节点解析并内嵌 SVG,解析失败回退占位并转诊断 - 新增 test_plot.py(13 个测试)覆盖表达式安全、指令解析、SVG 输出与导出链路集成 Co-Authored-By: Claude Code <noreply@anthropic.com>
- P1 浮点刻度死循环:_ticks 改为有上限的整数索引推进并校验步长推进 - P2 求值异常:白名单函数校验参数数量;负数底非整数指数按断点处理;采样容错复数 - P2 无效纵轴范围:退化/非有限 range 丢弃并自动采样重算;渲染异常回退占位不阻断导出 - 补 6 个回归测试 Co-Authored-By: Claude Code <noreply@anthropic.com>
同步 main(054f704),解决 contracts.py / main.py / README.md / 技术栈说明 的合并冲突。 - contracts.py:保留 pydantic 多行导入并新增 RequestOverride - main.py:合并 lifespan(导出孤儿清理 + 转写/本地模型生命周期) - README.md / 技术栈说明:文档取 main 最新版本 Co-Authored-By: Claude Code <noreply@anthropic.com>
- P2 复杂表达式绕过异常回退:解析与渲染共同纳入局部异常回退; AST 深度/节点数上限拦截 RecursionError - P2 极端有限范围生成 nan SVG:校验坐标跨度有限且 >0,回退安全范围; _polyline 拒绝非有限像素坐标 - P3 更新接口契约文档:function-plot 静态 SVG 已实现 Co-Authored-By: Claude Code <noreply@anthropic.com>
审阅提交:b87f945
b87f945
上一轮提出的 2 个 P2、1 个 P3 均已正确修复:
本轮复审新发现 1 个 P1。
位置:backend/app/plot/parser.py:363–370
backend/app/plot/parser.py:363–370
当前复杂度限制只作用于单条表达式,parse_source 可以无限追加合法表达式。
parse_source
实测结果:
y=x
未保存 Markdown 当前允许最多 200,000 个字符,可容纳约 50,000 行简单表达式,理论上会生成约 280 MB SVG,并执行约 4,000 万次采样求值。生成过程中还会存在中间字符串和编码副本,实际内存占用会更高。
同时:
asyncio.to_thread
note
MAX_MARKDOWN_CHARS
多个并发任务可能耗尽内存和工作线程。
建议:
markdown
git diff --check
请修复上述资源上限问题并补充测试后再提交复审。
No dependencies set.
The note is not visible to the blocked user.
概述
函数图像静态渲染(Function Plot)与导出服务(Markdown → HTML)的复审修复。本 PR 是
#28审阅结论(2 P2 + 1 P3)修复后的复审提交。本轮修复(对应
#28结论)ast深度(200)/节点数(1000)上限拦截RecursionError;解析与渲染共同纳入局部异常回退,单个图像失败只回退占位 + warning,不阻断整篇导出。nan的 SVG:新增跨度校验(端点有限、跨度有限且 >0),domain/range 无效时回退安全范围;_polyline拒绝非有限像素坐标。docs/contracts/第二阶段接口契约-开发版.md,标注function-plot已支持静态 SVG、失败回退占位。测试
backend全量pytest:621 passed(新增 5 项边界回归:超深表达式、超量节点、HTML 深表达式回退、极端 domain/range 无 nan/inf)。说明
backend/代码 + 接口契约文档。审阅结论:请求修改,暂不建议合并
审阅提交:
b87f945上一轮提出的 2 个 P2、1 个 P3 均已正确修复:
nan的 SVG;本轮复审新发现 1 个 P1。
[P1] 函数数量没有限制,可能生成数百 MB 的 SVG
位置:
backend/app/plot/parser.py:363–370当前复杂度限制只作用于单条表达式,
parse_source可以无限追加合法表达式。实测结果:
y=x:约 0.56 MB SVG;y=x:约 5.59 MB SVG;未保存 Markdown 当前允许最多 200,000 个字符,可容纳约 50,000 行简单表达式,理论上会生成约 280 MB SVG,并执行约 4,000 万次采样求值。生成过程中还会存在中间字符串和编码副本,实际内存占用会更高。
同时:
asyncio.to_thread中,取消请求在渲染结束前无法停止线程;note来源没有执行MAX_MARKDOWN_CHARS检查。多个并发任务可能耗尽内存和工作线程。
建议:
function-plot图块的表达式数量;note和markdown来源统一执行输入大小限制;验证结果
git diff --check:通过main:无冲突请修复上述资源上限问题并补充测试后再提交复审。
Pull request closed