1
0
mirror of https://github.com/django/django.git synced 2024-12-23 01:25:58 +00:00

Fixed #35667 -- Improved deprecation warning handling by replacing stacklevel with skip_file_prefixes.

Signed-off-by: saJaeHyukc <wogur981208@gmail.com>
This commit is contained in:
saJaeHyukc 2024-10-16 20:06:59 +09:00
parent 9ca1f6eff6
commit b698b0de37
3 changed files with 70 additions and 3 deletions

View File

@ -1,8 +1,12 @@
import inspect import inspect
import os
import warnings import warnings
from asgiref.sync import iscoroutinefunction, markcoroutinefunction, sync_to_async from asgiref.sync import iscoroutinefunction, markcoroutinefunction, sync_to_async
import django
from django.utils.version import PY312
class RemovedInDjango60Warning(DeprecationWarning): class RemovedInDjango60Warning(DeprecationWarning):
pass pass
@ -140,3 +144,25 @@ class MiddlewareMixin:
thread_sensitive=True, thread_sensitive=True,
)(request, response) )(request, response)
return response return response
def adjust_stacklevel_for_warning(skip_file_prefixes):
def _get_non_django_stacklevel():
django_path = os.path.dirname(django.__file__)
stacklevel = 1
# Exclude current and nested function frames with [2:].
for frame_info in inspect.stack()[2:]:
filename = os.path.abspath(frame_info.filename)
if not filename.startswith(django_path):
return stacklevel
stacklevel += 1
return 1
if PY312:
return {
"skip_file_prefixes": (
os.path.normpath(os.path.dirname(skip_file_prefixes)),
)
}
else:
return {"stacklevel": _get_non_django_stacklevel()}

View File

@ -221,7 +221,10 @@ previous behavior, or standalone items that are unnecessary or unused when the
deprecation ends. For example:: deprecation ends. For example::
import warnings import warnings
from django.utils.deprecation import RemovedInDjangoXXWarning from django.utils.deprecation import (
RemovedInDjangoXXWarning,
adjust_stacklevel_for_warning,
)
# RemovedInDjangoXXWarning. # RemovedInDjangoXXWarning.
@ -234,7 +237,7 @@ deprecation ends. For example::
warnings.warn( warnings.warn(
"foo() is deprecated.", "foo() is deprecated.",
category=RemovedInDjangoXXWarning, category=RemovedInDjangoXXWarning,
stacklevel=2, **adjust_stacklevel_for_warning(__file__),
) )
old_private_helper() old_private_helper()
... ...

View File

@ -1,5 +1,9 @@
import importlib.util
import os
import warnings import warnings
from pathlib import Path
import django
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.utils.deprecation import RemovedAfterNextVersionWarning, RenameMethodsBase from django.utils.deprecation import RemovedAfterNextVersionWarning, RenameMethodsBase
@ -178,3 +182,37 @@ class RenameMethodsTests(SimpleTestCase):
self.assertTrue( self.assertTrue(
issubclass(RemovedAfterNextVersionWarning, PendingDeprecationWarning) issubclass(RemovedAfterNextVersionWarning, PendingDeprecationWarning)
) )
class AdjustStacklevelForWarningTests(SimpleTestCase):
def test_warning_in_django_code(self):
self.django_path = Path(os.path.dirname(django.__file__))
self.temp_file_path = self.django_path / "temp_adjust_stacklevel_for_warning.py"
file_content = """
import warnings
from django.utils.deprecation import adjust_stacklevel_for_warning
def django_function():
warnings.warn(
"This is a test warning from Django code.",
DeprecationWarning,
**adjust_stacklevel_for_warning(__file__),
)
"""
self.temp_file_path.write_text(file_content)
module_name = "temp_adjust_stacklevel_for_warning"
spec = importlib.util.spec_from_file_location(
module_name, str(self.temp_file_path)
)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
msg = "This is a test warning from Django code."
with self.assertWarnsMessage(DeprecationWarning, msg) as ctx:
module.django_function()
self.assertEqual(ctx.filename, __file__)
self.temp_file_path.unlink()