From 068b2c072b0d28cbd5ea63811779629cdaad8638 Mon Sep 17 00:00:00 2001 From: mgaligniana Date: Wed, 15 Dec 2021 01:15:41 -0300 Subject: [PATCH] Fixed #30127 -- Deprecated name argument of cached_property(). --- django/utils/functional.py | 12 ++++++++-- docs/internals/deprecation.txt | 3 +++ docs/ref/utils.txt | 5 ++++ docs/releases/4.1.txt | 3 +++ tests/utils_tests/test_functional.py | 34 ++++++++++++++++++++++------ 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/django/utils/functional.py b/django/utils/functional.py index 5f12aa08ff..ea46cff20f 100644 --- a/django/utils/functional.py +++ b/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__') diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 7ee87d448a..3a3abfeb42 100644 --- a/docs/internals/deprecation.txt +++ b/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 diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index 0b68411e27..39c8e341ad 100644 --- a/docs/ref/utils.txt +++ b/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 `, the ``@classproperty`` diff --git a/docs/releases/4.1.txt b/docs/releases/4.1.txt index ee21c63a38..f2a168db40 100644 --- a/docs/releases/4.1.txt +++ b/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 ======================= diff --git a/tests/utils_tests/test_functional.py b/tests/utils_tests/test_functional.py index b870f98ea2..f720ffac3d 100644 --- a/tests/utils_tests/test_functional.py +++ b/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: