Opened 5 years ago

Closed 4 years ago

#30864 closed New feature (fixed)

Document and endorse django.utils.decorators.classproperty

Reported by: Julian Gonggrijp Owned by: Deep Sukhwani
Component: Documentation Version: dev
Severity: Normal Keywords: utils classproperty
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description

django.utils.decorators.classproperty is really useful. Please document it, encourage its use and make it a stable feature.

Change History (20)

comment:1 by Claude Paroz, 5 years ago

Personally, I'd love having cached_classproperty

comment:2 by Simon Charette, 5 years ago

Summary: Please document and endorse django.utils.decorators.classpropertyDocument and endorse django.utils.decorators.classproperty

Personally, I'd love having cached_classproperty

That would be hard to implement without some metaclass mockery or relying on some naive if not hasattr(cls, '_cached_foo') constructs.

cached_property is efficient because it relies on the descriptor protocol to cache its return value into __dict__ and avoid class level attribute lookups. We can't achieve similar things without defining the attribute on the class of the class (metaclass) and use the class's __dict__ as a cache store.

I guess the following could work.

class cached_classproperty:
    NOT_SET = object()

    def __init__(self, method):
        self.method = method
        self.cached_value = self.NOT_SET

    def __get__(self, instance, owner):
        if self.cached_value is not self.NOT_SET:
            return self.cached_value

        self.cached_value = self.method(owner)
        return self.cached_value

     def __set__(self, instance, value):
         self.cached_value = value

     def __delete__(self, instance):
         self.cached_value = self.NOT_SET

But this wouldn't be as efficient as cached_property because __get__ would always be called.

Anyway the cached_classproperty case should probably be discussed in another ticket or on the mailing list.

comment:3 by Carlton Gibson, 5 years ago

Triage Stage: UnreviewedAccepted

I don't see any harm in promoting this to public.

comment:4 by Mariusz Felisiak, 5 years ago

I can only add that it's already tested utils_tests.test_decorators.ClassPropertyTest. Documentation should land in docs/ref/utils.txt.

comment:5 by Claude Paroz, 5 years ago

Shouldn't it be moved to django.utils.functional?

comment:6 by Mariusz Felisiak, 5 years ago

Yes, good idea.

in reply to:  5 comment:7 by André Ericson, 5 years ago

Replying to Claude Paroz:

Shouldn't it be moved to django.utils.functional?

I've created a ticket for that https://code.djangoproject.com/ticket/30876 I think it makes more sense to address it first. I will go ahead and do it once it's accepted.

comment:8 by André Ericson, 4 years ago

Owner: changed from nobody to André Ericson
Status: newassigned

comment:9 by Mariusz Felisiak, 4 years ago

Owner: André Ericson removed
Status: assignednew

comment:10 by Sumit Patra, 4 years ago

Owner: set to Sumit Patra
Status: newassigned

comment:11 by Sumit Patra, 4 years ago

Owner: Sumit Patra removed
Status: assignednew

comment:12 by Deep Sukhwani, 4 years ago

Owner: set to Deep Sukhwani
Status: newassigned

comment:13 by Deep Sukhwani, 4 years ago

Has patch: set
Last edited 4 years ago by Deep Sukhwani (previous) (diff)

comment:14 by Deep Sukhwani, 4 years ago

For reviewers: Slightly confused since this is my first trac ticket in Django project. Please guide.

Three questions:

  • The version on this ticket says 2.2 however the change, i.e. move from django.utils.decorators to django.utils.functional was made in Django 3.1 (current ongoing development version) as a result of which, I added versionchanged text to the submitted code change. Should I remove versionchanged?
  • If the answer for above question is yes, does this mean this change needs to be backported to 2.2?
  • If the answer for above question is yes, then does this also need to be backported to every other version release since 2.2? i.e. all Versions: in 2.x.y series and versions in 3.0.x series?

in reply to:  14 ; comment:15 by Mariusz Felisiak, 4 years ago

Version: 2.2master

Replying to Deep Sukhwani:

  • The version on this ticket says 2.2 however the change, i.e. move from django.utils.decorators to django.utils.functional was made in Django 3.1 (current ongoing development version) as a result of which, I added versionchanged text to the submitted code change. Should I remove versionchanged?

This is a new feature so it goes only to the current master and should be targeted to the Django 3.1. versionchanged annotation is not necessary, you should add versionadded instead.

in reply to:  15 comment:16 by Deep Sukhwani, 4 years ago

Replying to felixxm:

This is a new feature so it goes only to the current master and should be targeted to the Django 3.1. versionchanged annotation is not necessary, you should add versionadded instead.

This feature (classproperty decorator) did exist in previous version, however it was part of a different module django.utils.decorators and in version 3.1 it is moved to django.utils.functional

Ref: https://docs.djangoproject.com/en/dev/releases/3.1/#id1, it says

django.utils.decorators.classproperty() decorator is moved to django.utils.functional.classproperty()

comment:17 by Mariusz Felisiak, 4 years ago

I know that, but it doesn't change anything, IMO. We've added this note in case someone uses this unsupported API. classproperty docs doesn't need to contain it.

comment:18 by Mariusz Felisiak, 4 years ago

Patch needs improvement: set

comment:19 by Mariusz Felisiak, 4 years ago

Patch needs improvement: unset
Triage Stage: AcceptedReady for checkin

comment:20 by Mariusz Felisiak <felisiak.mariusz@…>, 4 years ago

Resolution: fixed
Status: assignedclosed

In 4b146e0c:

Fixed #30864 -- Doc'd classproperty decorator.

Note: See TracTickets for help on using tickets.
Back to Top