Browse Source

Fixed #30127 -- Deprecated name argument of cached_property().

mgaligniana 3 years ago
parent
commit
068b2c072b

+ 10 - 2
django/utils/functional.py

@@ -1,6 +1,7 @@
 import copy
 import itertools
 import operator
+import warnings
 from functools import total_ordering, wraps
 
 
@@ -11,8 +12,6 @@ class cached_property:
 
     A cached property can be made out of an existing method:
     (e.g. ``url = cached_property(get_absolute_url)``).
-    The optional ``name`` argument is obsolete as of Python 3.6 and will be
-    deprecated in Django 4.0 (#30127).
     """
     name = None
 
@@ -24,6 +23,15 @@ class cached_property:
         )
 
     def __init__(self, func, name=None):
+        from django.utils.deprecation import RemovedInDjango50Warning
+
+        if name is not None:
+            warnings.warn(
+                "The name argument is deprecated as it's unnecessary as of "
+                "Python 3.6.",
+                RemovedInDjango50Warning,
+                stacklevel=2,
+            )
         self.real_func = func
         self.__doc__ = getattr(func, '__doc__')
 

+ 3 - 0
docs/internals/deprecation.txt

@@ -69,6 +69,9 @@ details on these changes.
 
 * The ``CSRF_COOKIE_MASKED`` transitional setting will be removed.
 
+* The ``name`` argument of ``django.utils.functional.cached_property()`` will
+  be removed.
+
 .. _deprecation-removed-in-4.1:
 
 4.1

+ 5 - 0
docs/ref/utils.txt

@@ -508,6 +508,11 @@ https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004
         z = person.friends         # does not call
         x is z                     # is True
 
+    .. deprecated:: 4.1
+
+        The ``name`` parameter is deprecated and will be removed in Django 5.0
+        as it's unnecessary as of Python 3.6.
+
 .. class:: classproperty(method=None)
 
     Similar to :py:func:`@classmethod <classmethod>`, the ``@classproperty``

+ 3 - 0
docs/releases/4.1.txt

@@ -346,6 +346,9 @@ Miscellaneous
 
 * ``CSRF_COOKIE_MASKED`` transitional setting is deprecated.
 
+* The ``name`` argument of :func:`django.utils.functional.cached_property` is
+  deprecated as it's unnecessary as of Python 3.6.
+
 Features removed in 4.1
 =======================
 

+ 27 - 7
tests/utils_tests/test_functional.py

@@ -1,6 +1,8 @@
 from unittest import mock
 
 from django.test import SimpleTestCase
+from django.test.utils import ignore_warnings
+from django.utils.deprecation import RemovedInDjango50Warning
 from django.utils.functional import cached_property, classproperty, lazy
 
 
@@ -97,12 +99,36 @@ class FunctionalTests(SimpleTestCase):
                 """Here is the docstring..."""
                 return 1, object()
 
-            other = cached_property(other_value, name='other')
+            other = cached_property(other_value)
 
         attrs = ['value', 'other', '__foo__']
         for attr in attrs:
             self.assertCachedPropertyWorks(attr, Class)
 
+    @ignore_warnings(category=RemovedInDjango50Warning)
+    def test_cached_property_name(self):
+        class Class:
+            def other_value(self):
+                """Here is the docstring..."""
+                return 1, object()
+
+            other = cached_property(other_value, name='other')
+            other2 = cached_property(other_value, name='different_name')
+
+        self.assertCachedPropertyWorks('other', Class)
+        # An explicit name is ignored.
+        obj = Class()
+        obj.other2
+        self.assertFalse(hasattr(obj, 'different_name'))
+
+    def test_cached_property_name_deprecation_warning(self):
+        def value(self):
+            return 1
+
+        msg = "The name argument is deprecated as it's unnecessary as of Python 3.6."
+        with self.assertWarnsMessage(RemovedInDjango50Warning, msg):
+            cached_property(value, name='other_name')
+
     def test_cached_property_auto_name(self):
         """
         cached_property caches its value and behaves like a property
@@ -119,17 +145,11 @@ class FunctionalTests(SimpleTestCase):
                 return 1, object()
 
             other = cached_property(other_value)
-            other2 = cached_property(other_value, name='different_name')
 
         attrs = ['_Class__value', 'other']
         for attr in attrs:
             self.assertCachedPropertyWorks(attr, Class)
 
-        # An explicit name is ignored.
-        obj = Class()
-        obj.other2
-        self.assertFalse(hasattr(obj, 'different_name'))
-
     def test_cached_property_reuse_different_names(self):
         """Disallow this case because the decorated function wouldn't be cached."""
         with self.assertRaises(RuntimeError) as ctx: