Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions Doc/library/warnings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ Available Functions
and calls to :func:`simplefilter`.


.. decorator:: deprecated(message, /, *, category=DeprecationWarning, stacklevel=1)
.. decorator:: deprecated(message, /, *, category=DeprecationWarning, stacklevel=1, skip_file_prefixes=())

Decorator to indicate that a class, function or overload is deprecated.

Expand Down Expand Up @@ -598,12 +598,14 @@ Available Functions
on use of deprecated objects. For functions, that happens on calls;
for classes, on instantiation and on creation of subclasses.
If the *category* is ``None``, no warning is emitted at runtime.
The *stacklevel* determines where the
warning is emitted. If it is ``1`` (the default), the warning
The *stacklevel* and *skip_file_prefixes* entries determine where the
warning is emitted. If *stacklevel* is ``1`` (the default), the warning
is emitted at the direct caller of the deprecated object; if it
is higher, it is emitted further up the stack.
Static type checker behavior is not affected by the *category*
and *stacklevel* arguments.
Frames in files whose path starts with any of the strings in
*skip_file_prefixes* are skipped.
Static type checker behavior is not affected by the *category*,
*skip_file_prefixes*, and *stacklevel* arguments.

The deprecation message passed to the decorator is saved in the
``__deprecated__`` attribute on the decorated object.
Expand All @@ -615,6 +617,9 @@ Available Functions
.. versionadded:: 3.13
See :pep:`702`.

.. versionchanged:: 3.16
Added *skip_file_prefixes*.


Available Context Managers
--------------------------
Expand Down
21 changes: 13 additions & 8 deletions Lib/_py_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import sys
import _contextvars
import _thread
lazy from collections.abc import Iterable


__all__ = ["warn", "warn_explicit", "showwarning",
Expand Down Expand Up @@ -763,12 +764,14 @@ def g(x: str) -> int: ...
on use of deprecated objects. For functions, that happens on calls;
for classes, on instantiation and on creation of subclasses.
If the *category* is ``None``, no warning is emitted at runtime.
The *stacklevel* determines where the
warning is emitted. If it is ``1`` (the default), the warning
The *stacklevel* and *skip_file_prefixes* entries determine where the
warning is emitted. If *stacklevel* is ``1`` (the default), the warning
is emitted at the direct caller of the deprecated object; if it
is higher, it is emitted further up the stack.
Static type checker behavior is not affected by the *category*
and *stacklevel* arguments.
Frames in files whose path starts with any of the strings in
*skip_file_prefixes* are skipped.
Static type checker behavior is not affected by the *category*,
*skip_file_prefixes*, and *stacklevel* arguments.

The deprecation message passed to the decorator is saved in the
``__deprecated__`` attribute on the decorated object.
Expand All @@ -786,6 +789,7 @@ def __init__(
*,
category: type[Warning] | None = DeprecationWarning,
stacklevel: int = 1,
skip_file_prefixes: Iterable[str] = (),
) -> None:
if not isinstance(message, str):
raise TypeError(
Expand All @@ -794,6 +798,7 @@ def __init__(
self.message = message
self.category = category
self.stacklevel = stacklevel
self.skip_file_prefixes = tuple(skip_file_prefixes)

def __call__(self, arg, /):
# Make sure the inner functions created below don't
Expand All @@ -813,7 +818,7 @@ def __call__(self, arg, /):
@functools.wraps(original_new)
def __new__(cls, /, *args, **kwargs):
if cls is arg:
_wm.warn(msg, category=category, stacklevel=stacklevel + 1)
_wm.warn(msg, category=category, stacklevel=stacklevel + 1, skip_file_prefixes=self.skip_file_prefixes)
if original_new is not object.__new__:
return original_new(cls, *args, **kwargs)
# Mirrors a similar check in object.__new__.
Expand All @@ -837,11 +842,11 @@ def __new__(cls, /, *args, **kwargs):

@functools.wraps(original_init_subclass)
def __init_subclass__(*args, **kwargs):
_wm.warn(msg, category=category, stacklevel=stacklevel + 1)
_wm.warn(msg, category=category, stacklevel=stacklevel + 1, skip_file_prefixes=self.skip_file_prefixes)
return original_init_subclass(*args, **kwargs)
else:
def __init_subclass__(cls, *args, **kwargs):
_wm.warn(msg, category=category, stacklevel=stacklevel + 1)
_wm.warn(msg, category=category, stacklevel=stacklevel + 1, skip_file_prefixes=self.skip_file_prefixes)
return super(arg, cls).__init_subclass__(*args, **kwargs)

arg.__init_subclass__ = classmethod(__init_subclass__)
Expand All @@ -855,7 +860,7 @@ def __init_subclass__(cls, *args, **kwargs):

@functools.wraps(arg)
def wrapper(*args, **kwargs):
_wm.warn(msg, category=category, stacklevel=stacklevel + 1)
_wm.warn(msg, category=category, stacklevel=stacklevel + 1, skip_file_prefixes=self.skip_file_prefixes)
return arg(*args, **kwargs)

if inspect.iscoroutinefunction(arg):
Expand Down
19 changes: 19 additions & 0 deletions Lib/test/test_warnings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2252,6 +2252,25 @@ def c():
with self.assertWarnsRegex(RuntimeWarning, "c will go away soon"):
c()

def test_skip_file_prefixes(self):
code = """\
from warnings import deprecated

@deprecated("good as gone", skip_file_prefixes=(__file__,))
def nested_func() -> Outer:
pass
"""
mod = types.ModuleType("mod")
mod.__file__ = "/fictional/path/my_test_file.py"
exec(code, mod.__dict__)

with py_warnings.catch_warnings(record=True) as record:
py_warnings.simplefilter("always")
lineno_expected = sys._getframe().f_lineno + 1 # next line
mod.nested_func()

assert (record[0].filename, record[0].lineno) == (__file__, lineno_expected)

def test_turn_off_warnings(self):
@deprecated("d will go away soon", category=None)
def d():
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add ``skip_file_prefixes`` parameter to :deco:`warnings.deprecated`, mirroring the parameter of the same name for :func:`warnings.warn`.
Loading