2.9 KiB
Raw Blame History

name description
dspy-patterns Use when writing DSPY. sqlor, Python bools, IN lists.

DSPY File Writing Patterns

Python vs JSON boolean

Use Python True/False, not JSON true/false:

{"autoplay": True}          # CORRECT
{"autoplay": true}          # NameError

sqlor %% escaping

"WHERE x LIKE '%%pattern%%'"  → SQL: WHERE x LIKE '%pattern%'

sqlor IN lists

Some sqlor versions fail on ${ids}$ list expansion. Use manual SQL:

id_list = ','.join(["'" + str(x) + "'" for x in ids])
sql = "WHERE id IN (" + id_list + ")"

URL in widgets

Use entire_url() for full URLs:

media_url = entire_url(safe_url(path))
# "/idfile/44/file.mp4" → "https://host/idfile/44/file.mp4"

Debug silent failures

Replace except Exception: pass with:

except Exception as e:
    return {"widgettype":"Text","options":{"text":f"ERR:{e}"}}

f-string 禁止CRITICAL

DSPY 文件在受限的 exec() 命名空间中执行。f-string 在 dict 字面量中会导致语法错误

# ❌ SyntaxError: '{' was never closed
return {"widgettype": "Text", "options": {"otext": f'算力池: {n} 个'}}

# ❌ unittest string literal
return {'widgettype': 'Text', 'options': {'otext': f'存储: {total}GB'}}

# ✅ 使用字符串拼接
return {"widgettype": "Text", "options": {"otext": '算力池: ' + str(n) + ' 个'}}

错误日志特征:except=unterminated string literal (detected at line X)

返回 FileResponse 提供文件下载/媒体流

DSPY 可直接返回 aiohttp FileResponse 服务任意文件系统路径,因为 BaseProcessor.handle() 检查 isinstance(self.content, StreamResponse) 直接返回,绕过 JSON 序列化:

import os
from urllib.parse import quote
from aiohttp.web_fileresponse import FileResponse

full_path = ws_dir + '/' + file_id  # 任意绝对路径,不必在 FileStorage

# 路径穿越校验
real_ws = os.path.realpath(ws_dir)
real_full = os.path.realpath(full_path)
if not real_full.startswith(real_ws + os.sep):
    return {"widgettype": "Message", "options": {"title": "错误", "message": "非法路径"}}

headers = {}
if download:
    filename = os.path.basename(full_path)
    headers['Content-Disposition'] = 'attachment; filename="%s"; filename*=UTF-8\'\'%s' % (filename, quote(filename))

return FileResponse(full_path, headers=headers)
  • download 参数 → 流式返回,FileResponse 自动探测 MIME。VideoPlayer/AudioPlayer/Imageurl 直接指向此 DSPYentire_url("/module/api/file.dspy") + "?id=" + quote(rel_path))。
  • download=1Content-Disposition: attachment 触发浏览器下载office/pdf 下载后本地应用打开)。
  • 对比 idfile(只服务 FileStorage的优势可服务任意目录如项目工作区不受 FileStorage.realPath 的 root 限制。