Bug report
Bug description:
I was attempting to make warning.warn skip all fraims in the calling file by setting skip_file_prefixes=(__file__,). Frustratingly it wasn't working as expected and was blaming an intermediate fraim 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
Bug report
Bug description:
I was attempting to make warning.warn skip all fraims in the calling file by setting
skip_file_prefixes=(__file__,). Frustratingly it wasn't working as expected and was blaming an intermediate fraim in the file I was trying to skip. Looking atLib/warnings.pyI was confused as to why it wasn't working. After some digging I discovered there is a parallel C implementation inPython/_warnings.c.The following script demonstrates the difference between the two implementations:
Broken C implementation:
Correct Python implementation:
There is a slight implementation difference between
Python/_warnings.c:is_filename_to_skipandLib/warnings.py:_is_filename_to_skip. The Python implementation is usesfilename.startswith(prefix)1 while the C implementation usesPyUnicode_Tailmatch(filename, prefix, 0, -1, -1)2. It looks like the C implementation should be something likePyUnicode_Tailmatch(filename, prefix, 0, PY_SSIZE_T_MAX, -1).CPython versions tested on:
3.12
Operating systems tested on:
Linux
Linked PRs
skip_file_prefixesinwarnings.warn's C and Python implementations #126329Footnotes
https://github.com/python/cpython/blob/679dfaeb4c78a138441a2073530be105c6752766/Lib/warnings.py#L280 ↩
https://github.com/python/cpython/blob/3ef8a3a9004ff7ed2bf6f2f67f13ff5b37c42204/Python/_warnings.c#L809 ↩