python / python/cpython

warn_explicit() discards the source line obtained from module_globals

未关闭
#155,319 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

3.13 3.14 3.15 3.16 extension-modules type-bug
主要语言
Python
星标
77.2k
派生
36k
PR 合并指标
PR 指标待抓取

描述

The only purpose of the module_globals argument of warnings.warn_explicit() is to get the source line of the warning from the module loader when the file cannot be read. The C implementation computes it in get_source_line(), but then throws it away.

call_show_warning() passes None in the line slot of WarningMessage and ignores its own sourceline argument:

    msg = PyObject_CallFunctionObjArgs(warnmsg_cls, message, category,
            filename, lineno_obj, Py_None, Py_None,
            source ? source : Py_None, module,
            NULL);

sourceline is only used in the fallback show_warning() path, taken when warnings._showwarnmsg is not available.

As a result the source line is lost, while the pure Python implementation, which seeds linecache instead, displays it:

$ cat > spam.py <<EOF
import warnings
def f():
    warnings.warn_explicit('eggs', UserWarning, 'bar', 1, module_globals=globals())
EOF
$ ./python -c 'import spam; spam.f()'
bar:1: UserWarning: eggs
$ ./python -c 'import sys; sys.modules["_warnings"] = None; import spam; spam.f()'
bar:1: UserWarning: eggs
  import warnings

The None was added in 914cde89d4c together with the source argument, so the C implementation has never passed the source line.

Linked PRs
  • gh-155320
  • gh-155824
  • gh-155825
  • gh-155826

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从 C 函数 get_source_line() 和 call_show_warning() 入手,issue 指出它们会计算源代码行,然后将其丢弃。复现 issue 中的 warn_explicit() 示例,并验证源代码行在 WarningMessage 路径以及备用的 show_warning() 路径中都得到保留。

由索引模型根据 Issue 内容生成。

评估

技术栈
c, python
领域
backend
Issue 类型
缺陷
难度
3/5
预计耗时
1-2 天
活跃度
停滞
描述清晰度
描述清楚
新手友好度
25/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。