mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	Fixed #30876 -- Moved classproperty() decorator to the django.utils.functional.
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							31174031f1
						
					
				
				
					commit
					3120490912
				
			| @@ -1,7 +1,7 @@ | |||||||
| from django.apps.registry import Apps | from django.apps.registry import Apps | ||||||
| from django.db import models | from django.db import models | ||||||
| from django.db.utils import DatabaseError | 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 django.utils.timezone import now | ||||||
|  |  | ||||||
| from .exceptions import MigrationSchemaMissing | from .exceptions import MigrationSchemaMissing | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import unittest | |||||||
| from contextlib import contextmanager | from contextlib import contextmanager | ||||||
|  |  | ||||||
| from django.test import LiveServerTestCase, tag | 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.module_loading import import_string | ||||||
| from django.utils.text import capfirst | from django.utils.text import capfirst | ||||||
|  |  | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ from django.test.utils import ( | |||||||
|     CaptureQueriesContext, ContextList, compare_xml, modify_settings, |     CaptureQueriesContext, ContextList, compare_xml, modify_settings, | ||||||
|     override_settings, |     override_settings, | ||||||
| ) | ) | ||||||
| from django.utils.decorators import classproperty | from django.utils.functional import classproperty | ||||||
| from django.views.static import serve | from django.views.static import serve | ||||||
|  |  | ||||||
| __all__ = ('TestCase', 'TransactionTestCase', | __all__ = ('TestCase', 'TransactionTestCase', | ||||||
|   | |||||||
| @@ -150,15 +150,3 @@ def make_middleware_decorator(middleware_class): | |||||||
|             return _wrapped_view |             return _wrapped_view | ||||||
|         return _decorator |         return _decorator | ||||||
|     return _make_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 |  | ||||||
|   | |||||||
| @@ -49,6 +49,18 @@ class cached_property: | |||||||
|         return res |         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: | class Promise: | ||||||
|     """ |     """ | ||||||
|     Base class for the proxy class created in the closure of the lazy function. |     Base class for the proxy class created in the closure of the lazy function. | ||||||
|   | |||||||
| @@ -263,6 +263,9 @@ Miscellaneous | |||||||
|   ``ETag`` header to responses with an empty |   ``ETag`` header to responses with an empty | ||||||
|   :attr:`~django.http.HttpResponse.content`. |   :attr:`~django.http.HttpResponse.content`. | ||||||
|  |  | ||||||
|  | * ``django.utils.decorators.classproperty()`` decorator is moved to | ||||||
|  |   ``django.utils.functional.classproperty()``. | ||||||
|  |  | ||||||
| .. _deprecated-features-3.1: | .. _deprecated-features-3.1: | ||||||
|  |  | ||||||
| Features deprecated in 3.1 | Features deprecated in 3.1 | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ from django.http import HttpResponse | |||||||
| from django.template import engines | from django.template import engines | ||||||
| from django.template.response import TemplateResponse | from django.template.response import TemplateResponse | ||||||
| from django.test import RequestFactory, SimpleTestCase | 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: | class ProcessViewMiddleware: | ||||||
| @@ -108,41 +108,3 @@ class DecoratorFromMiddlewareTests(SimpleTestCase): | |||||||
|         self.assertTrue(getattr(request, 'process_response_reached', False)) |         self.assertTrue(getattr(request, 'process_response_reached', False)) | ||||||
|         # process_response saw the rendered content |         # process_response saw the rendered content | ||||||
|         self.assertEqual(request.process_response_content, b"Hello world") |         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) |  | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| from unittest import mock | from unittest import mock | ||||||
|  |  | ||||||
| from django.test import SimpleTestCase | 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): | class FunctionalTests(SimpleTestCase): | ||||||
| @@ -218,3 +218,39 @@ class FunctionalTests(SimpleTestCase): | |||||||
|         with mock.patch.object(__proxy__, '__prepare_class__') as mocked: |         with mock.patch.object(__proxy__, '__prepare_class__') as mocked: | ||||||
|             lazified() |             lazified() | ||||||
|             mocked.assert_not_called() |             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) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user