pytest 表达式误报反斜杠转义:标识符与字符串被混查
表达式的反斜杠在标识符中,字符串参数本身没有转义,旧扫描器仍可能报 escaping not supported。pytest 9.1.0 已将检查范围收回当前字符串片段。
pytest 表达式报 escaping with "\" not supported in marker expression,但反斜杠实际在标识符里,字符串参数只是普通文本。这时需要区分词法扫描器误查了整个表达式,还是字符串值本身确实包含了不支持的转义。
pytest 9.1.0 已修正这一扫描范围问题,正式 9.2.0 也保留修正。修正只让扫描器检查当前字符串片段,不会让字符串参数自动支持反斜杠转义,也不扩展 -k、-m 各自的选择语义。
字符出现的位置决定问题性质
对维护插件或分析选择表达式的人,下面的内部解析示例能区分两个位置:
from _pytest.mark.expression import Expression
expression = Expression.compile(r'test\nfoo\n and mark(x="y")')
这里 test\nfoo\n 的反斜杠属于标识符文本,"y" 中没有反斜杠。旧扫描器处理到字符串时,却在完整输入中搜索反斜杠,于是把前面的字符当成字符串转义并拒绝。
这是私有解析接口的诊断片段,不是推荐在项目中依赖 _pytest 内部模块,也不是一条可直接照搬的 -k 选测试命令。语法编译通过后,关键字匹配和 marker 匹配仍有各自的求值规则;不能把 marker 参数调用混入不支持它的选择器,再把后续错误归给扫描器。
采用修正版,保留原选择条件
受这条回归影响的环境,应通过项目依赖管理使用包含修正的正式版本,再以真实选择表达式核对收集结果。新实现只在当前字符串片段寻找反斜杠,若确实存在,仍抛转义错误,并按片段在原输入中的位置报告列号。
如果字符串参数本身含有路径反斜杠,例如希望直接放入 Windows 路径,不能靠升级这项修正就认定合法。应重新审查 marker 的参数设计或采用该接口支持的值,避免把任意路径直接嵌入选择表达式。
也不要给整个表达式调用 re.escape()。pytest 选择表达式不是普通正则,转义其中的括号、运算符和引号会改变语法。这与 pytest.raises(match=...) 需要按正则处理固定异常文本是不同问题。
验收除了确认不再误报,还要核对应选中的 nodeid、数量与未选中的用例。原本应报错的字符串转义不能被悄悄接受;去掉整段选择条件后跑出绿色结果,也不能说明原选择规则已经恢复。


