python / cpython

The Python programming language
https://www.python.org
Other
63.38k stars 30.35k forks source link

warnings.warn's skip_file_prefixes doesn't work when provided `__file__`. #126209

Open nairb774 opened 1 week ago

nairb774 commented 1 week ago

Bug report

Bug description:

I was attempting to make warning.warn skip all frames in the calling file by setting skip_file_prefixes=(__file__,). Frustratingly it wasn't working as expected and was blaming an intermediate frame in the file I was trying to skip. Looking at Lib/warnings.py I was confused as to why it wasn't working. After some digging I discovered there is a parallel C implementation in Python/_warnings.c.

The following script demonstrates the difference between the two implementations:

import sys
# Uncomment to compare the C and Py implementation of warnings.warn.
# sys.modules["_warnings"] = None
import warnings

# Desired input which works as expected with the Py impl, but not the C impl.
skip_file_prefixes=(__file__,)

# Hack to make the C implementation match the Py behavior:
# skip_file_prefixes=(__file__[:-1],)  

def ccc():
    warnings.warn("Hello", UserWarning, skip_file_prefixes=skip_file_prefixes)

def bbb():
    ccc()

def aaa():
    bbb()

aaa()

Broken C implementation:

$ python sample.py 
/tmp/sample.py:12: UserWarning: Hello
  ccc()

Correct Python implementation:

$ python sample.py 
sys:1: UserWarning: Hello

There is a slight implementation difference between Python/_warnings.c:is_filename_to_skip and Lib/warnings.py:_is_filename_to_skip. The Python implementation is uses filename.startswith(prefix) ^1 while the C implementation uses PyUnicode_Tailmatch(filename, prefix, 0, -1, -1) ^2. It looks like the C implementation should be something like PyUnicode_Tailmatch(filename, prefix, 0, PY_SSIZE_T_MAX, -1).

$ python --version
Python 3.12.7

CPython versions tested on:

3.12

Operating systems tested on:

Linux

Linked PRs

zsaladin commented 6 days ago

I will take a look

corona10 commented 6 days ago

@zsaladin is a first-time contributor who is participating in the PyCon KR sprint today. I will help him contribute to this issue :)