summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Ericson <de.ericson@gmail.com>2019-10-18 21:00:34 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2019-10-21 09:57:39 +0200
commit312049091288dbba2299de8d07ea3e3311ed7238 (patch)
treef279e94af6d3fe6bddb33afcb0ce8928b9cf1fd6
parent31174031f1ded30d96c77908b965755e0be94c94 (diff)
Fixed #30876 -- Moved classproperty() decorator to the django.utils.functional.
-rw-r--r--django/db/migrations/recorder.py2
-rw-r--r--django/test/selenium.py2
-rw-r--r--django/test/testcases.py2
-rw-r--r--django/utils/decorators.py12
-rw-r--r--django/utils/functional.py12
-rw-r--r--docs/releases/3.1.txt3
-rw-r--r--tests/utils_tests/test_decorators.py40
-rw-r--r--tests/utils_tests/test_functional.py38
8 files changed, 56 insertions, 55 deletions
diff --git a/django/db/migrations/recorder.py b/django/db/migrations/recorder.py
index c3ed4148e7..20f5a7d85e 100644
--- a/django/db/migrations/recorder.py
+++ b/django/db/migrations/recorder.py
@@ -1,7 +1,7 @@
from django.apps.registry import Apps
from django.db import models
from django.db.utils import DatabaseError
-from django.utils.decorators import classproperty
+from django.utils.functional import classproperty
from django.utils.timezone import now
from .exceptions import MigrationSchemaMissing
diff --git a/django/test/selenium.py b/django/test/selenium.py
index 8910faec98..a114f77d14 100644
--- a/django/test/selenium.py
+++ b/django/test/selenium.py
@@ -3,7 +3,7 @@ import unittest
from contextlib import contextmanager
from django.test import LiveServerTestCase, tag
-from django.utils.decorators import classproperty
+from django.utils.functional import classproperty
from django.utils.module_loading import import_string
from django.utils.text import capfirst
diff --git a/django/test/testcases.py b/django/test/testcases.py
index ca5712ee8d..23459f22cd 100644
--- a/django/test/testcases.py
+++ b/django/test/testcases.py
@@ -37,7 +37,7 @@ from django.test.utils import (
CaptureQueriesContext, ContextList, compare_xml, modify_settings,
override_settings,
)
-from django.utils.decorators import classproperty
+from django.utils.functional import classproperty
from django.views.static import serve
__all__ = ('TestCase', 'TransactionTestCase',
diff --git a/django/utils/decorators.py b/django/utils/decorators.py
index 8e274b61af..4dc6c18f45 100644
--- a/django/utils/decorators.py
+++ b/django/utils/decorators.py
@@ -150,15 +150,3 @@ def make_middleware_decorator(middleware_class):
return _wrapped_view
return _decorator
return _make_decorator
-
-
-class classproperty:
- def __init__(self, method=None):
- self.fget = method
-
- def __get__(self, instance, cls=None):
- return self.fget(cls)
-
- def getter(self, method):
- self.fget = method
- return self
diff --git a/django/utils/functional.py b/django/utils/functional.py
index 1b81d414fa..bc3b65b709 100644
--- a/django/utils/functional.py
+++ b/django/utils/functional.py
@@ -49,6 +49,18 @@ class cached_property:
return res
+class classproperty:
+ def __init__(self, method=None):
+ self.fget = method
+
+ def __get__(self, instance, cls=None):
+ return self.fget(cls)
+
+ def getter(self, method):
+ self.fget = method
+ return self
+
+
class Promise:
"""
Base class for the proxy class created in the closure of the lazy function.
diff --git a/docs/releases/3.1.txt b/docs/releases/3.1.txt
index 656649f914..300c7a2c26 100644
--- a/docs/releases/3.1.txt
+++ b/docs/releases/3.1.txt
@@ -263,6 +263,9 @@ Miscellaneous
``ETag`` header to responses with an empty
:attr:`~django.http.HttpResponse.content`.
+* ``django.utils.decorators.classproperty()`` decorator is moved to
+ ``django.utils.functional.classproperty()``.
+
.. _deprecated-features-3.1:
Features deprecated in 3.1
diff --git a/tests/utils_tests/test_decorators.py b/tests/utils_tests/test_decorators.py
index fe5db876ef..367e78a4ad 100644
--- a/tests/utils_tests/test_decorators.py
+++ b/tests/utils_tests/test_decorators.py
@@ -2,7 +2,7 @@ from django.http import HttpResponse
from django.template import engines
from django.template.response import TemplateResponse
from django.test import RequestFactory, SimpleTestCase
-from django.utils.decorators import classproperty, decorator_from_middleware
+from django.utils.decorators import decorator_from_middleware
class ProcessViewMiddleware:
@@ -108,41 +108,3 @@ class DecoratorFromMiddlewareTests(SimpleTestCase):
self.assertTrue(getattr(request, 'process_response_reached', False))
# process_response saw the rendered content
self.assertEqual(request.process_response_content, b"Hello world")
-
-
-class ClassPropertyTest(SimpleTestCase):
- def test_getter(self):
- class Foo:
- foo_attr = 123
-
- def __init__(self):
- self.foo_attr = 456
-
- @classproperty
- def foo(cls):
- return cls.foo_attr
-
- class Bar:
- bar = classproperty()
-
- @bar.getter
- def bar(cls):
- return 123
-
- self.assertEqual(Foo.foo, 123)
- self.assertEqual(Foo().foo, 123)
- self.assertEqual(Bar.bar, 123)
- self.assertEqual(Bar().bar, 123)
-
- def test_override_getter(self):
- class Foo:
- @classproperty
- def foo(cls):
- return 123
-
- @foo.getter
- def foo(cls):
- return 456
-
- self.assertEqual(Foo.foo, 456)
- self.assertEqual(Foo().foo, 456)
diff --git a/tests/utils_tests/test_functional.py b/tests/utils_tests/test_functional.py
index af4bd197a6..6e454cfef3 100644
--- a/tests/utils_tests/test_functional.py
+++ b/tests/utils_tests/test_functional.py
@@ -1,7 +1,7 @@
from unittest import mock
from django.test import SimpleTestCase
-from django.utils.functional import cached_property, lazy
+from django.utils.functional import cached_property, classproperty, lazy
class FunctionalTests(SimpleTestCase):
@@ -218,3 +218,39 @@ class FunctionalTests(SimpleTestCase):
with mock.patch.object(__proxy__, '__prepare_class__') as mocked:
lazified()
mocked.assert_not_called()
+
+ def test_classproperty_getter(self):
+ class Foo:
+ foo_attr = 123
+
+ def __init__(self):
+ self.foo_attr = 456
+
+ @classproperty
+ def foo(cls):
+ return cls.foo_attr
+
+ class Bar:
+ bar = classproperty()
+
+ @bar.getter
+ def bar(cls):
+ return 123
+
+ self.assertEqual(Foo.foo, 123)
+ self.assertEqual(Foo().foo, 123)
+ self.assertEqual(Bar.bar, 123)
+ self.assertEqual(Bar().bar, 123)
+
+ def test_classproperty_override_getter(self):
+ class Foo:
+ @classproperty
+ def foo(cls):
+ return 123
+
+ @foo.getter
+ def foo(cls):
+ return 456
+
+ self.assertEqual(Foo.foo, 456)
+ self.assertEqual(Foo().foo, 456)