Commit 5ffa4cc4 authored by Data Governance Dev's avatar Data Governance Dev

fix(web3): 日期规则 datetime.strptime 缺模块限定符 → datetime.datetime.strptime

沙箱里 datetime 是模块名(不是 from datetime import datetime),
datetime.strptime / datetime.now 在沙箱里直接 AttributeError。

三处误导性的写法全部修正:

1. backend/core/ai_rule.py
   - _DATE_USER_TEMPLATE_INITIAL / _DATE_USER_TEMPLATE_FIX 两份 prompt
     把 datetime.strptime 改成 datetime.datetime.strptime,
     并加粗警告『绝对不能写成 datetime.strptime(会 AttributeError)』
   - 顺手修一笔 def check(value) -> str -> bool 的笔误(多写了 -> str)

2. src/components/RuleModal.vue
   - codePlaceholder(date) 改用 datetime.datetime.strptime,
     注释里点明沙箱语义
   - date 类型的 form-hint 改用 datetime.datetime.strptime,
     并加红字 warning 警示『不是 datetime.strptime』

3. tests/test_rule_runner.py
   - TestDate 加 test_datetime_strptime_without_module_qualifier_fails_clearly
     锁定『datetime.strptime(缺 .datetime.)必然 AttributeError』这个行为,
     防止哪天有人悄悄做成兼容(破坏语义清晰度)

注:已有坏规则(如 attendance_in_time 已落库 4 处)用户自行到 UI 改,
按 CLAUDE.md『本工具只做查询』原则不动 DB。
39 条测试全过。
parent 1dffa7f9
......@@ -76,10 +76,12 @@ _DATE_USER_TEMPLATE_INITIAL = """请把以下规则描述转换成一个 Python
规则描述:「{desc}」
要求:
1. 定义函数 def check(value) -> str -> bool:
1. 定义函数 def check(value) -> bool:
- value 是从数据库读出来的原始字符串(如 "2024-01-15"、"2024/01/15"、"20240115")
- 返回 True 表示合规,False 表示不合规
2. 用 datetime.strptime(v, '<format>') 解析日期,解析失败返回 False
2. 用 datetime.datetime.strptime(v, '<format>') 解析日期,解析失败返回 False
沙箱里 datetime 是模块名(不是 from datetime import datetime),
所以必须是「datetime.datetime.strptime」,**绝对不能写成「datetime.strptime」**(会 AttributeError)
3. 函数要短小(一般不超过 10 行),只做这一项校验
4. 不要写 import 语句,datetime 模块已经预注入到命名空间里
5. 如果描述里包含具体格式(如"yyyy-MM-dd"、"yyyyMMdd")或范围(如"晚于 2020-01-01"),一定要用上
......@@ -98,7 +100,8 @@ _DATE_USER_TEMPLATE_FIX = """上一次生成的代码有问题。
请输出修复后的 def check(value) -> bool: 函数。
要求:
1. 用 datetime.strptime(v, '<format>') 解析日期,解析失败返回 False
1. 用 datetime.datetime.strptime(v, '<format>') 解析日期(沙箱里 datetime 是模块名,
所以必须是「datetime.datetime.strptime」——「datetime.strptime」会 AttributeError)
2. 修掉上面的错误(语法 / 缺 check / 运行时异常)
3. 仍然不要写 import
......
......@@ -73,7 +73,8 @@
</div>
<div class="form-hint">
<span v-if="rule.rule_type === 'date'">
datetime 模块已预注入,直接用 datetime.strptime(v, '%Y-%m-%d') 即可;不需要 import。
datetime 模块已预注入,用 <code>datetime.datetime.strptime(v, '%Y-%m-%d')</code> 即可;不需要 import。
<strong style="color: #f56c6c;">注意是 <code>datetime.datetime.strptime</code>(模块.类.方法),不是 <code>datetime.strptime</code>(会 AttributeError)。</strong>
</span>
<span v-else>
需要数学常量时用 math 模块;不需要 import。
......@@ -152,7 +153,8 @@ function descPlaceholder(rt) {
}
function codePlaceholder(rt) {
if (rt === 'date') {
return 'def check(value) -> bool:\n try:\n d = datetime.strptime(value, "%Y-%m-%d")\n return d >= datetime.datetime(2020, 1, 1)\n except Exception:\n return False'
// 沙箱里 datetime 是模块名,所以必须是 datetime.datetime.strptime(不是 datetime.strptime,会 AttributeError)
return 'def check(value) -> bool:\n try:\n d = datetime.datetime.strptime(value, "%Y-%m-%d")\n return d >= datetime.datetime(2020, 1, 1)\n except Exception:\n return False'
}
return 'def check(value) -> bool:\n try:\n n = float(value)\n return 0 <= n <= 150\n except Exception:\n return False'
}
......
......@@ -93,6 +93,26 @@ class TestDate:
assert run_rule("date", None, code, "2024/01/15") is False
assert run_rule("date", None, code, "not-a-date") is False
def test_datetime_strptime_without_module_qualifier_fails_clearly(self):
"""用户/AI 偶尔会写成 `datetime.strptime(...)`(缺 `.datetime.`),
沙箱里 datetime 是模块名不是类,必须 AttributeError 报出来。
锁定这个行为,避免哪天有人悄悄把它做成兼容(破坏语义清晰度)。
注意 check() 不能包 try/except:包了就吞掉 AttributeError,返 False 而不报错,
用户看不到原因。正确做法是让 AttributeError 冒泡到 _exec_user_function,
包成 RuleRunError("check() 调用异常:...") 报回给用户。
"""
code = (
"def check(value):\n"
" datetime.strptime(value, '%Y-%m-%d')\n" # ← 故意错(模块没有 strptime)
" return True\n"
)
with pytest.raises(RuleRunError) as exc:
run_rule("date", None, code, "2024-01-15")
# 错误信息应明确指出 AttributeError + 模块没有 strptime
assert "AttributeError" in str(exc.value)
assert "strptime" in str(exc.value)
# ── 沙箱安全 ────────────────────────────────────────────
class TestSandbox:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment