ruff icon indicating copy to clipboard operation
ruff copied to clipboard

[django] New rule: Check that enums do not have a `do_not_call_in_templates` member

Open Kakadus opened this issue 1 year ago • 0 comments

In django templates, if a template variable is callable, the template system will try calling it. To disable that, one can define a truthy do_not_call_in_templates attribute on the callable [ref. django docs].

A fallacy might be to do something like the following:

from enum import Enum, auto


class AwesomeEnum(Enum):
    do_not_call_in_templates = True

    CASE_A = auto()
    CASE_B = auto()

Note that that leads do_not_call_in_templates to be e.g. in __members__, and maps to AwesomeEnum(True):

>>> AwesomeEnum.__members__
{'do_not_call_in_templates': <AwesomeEnum.do_not_call_in_templates: True>, 'CASE_A': <AwesomeEnum.CASE_A: 2>, 'CASE_B': <AwesomeEnum.CASE_B: 3>}

Instead, it should either be wrapped in an enum.nonmember or defined in a @property, so that it is not exported as a member of the enum like django itself does it.

A correct Enum would be defined like so:

from enum import Enum, auto, nonmember


class AwesomeEnum(Enum):
    do_not_call_in_templates = nonmember(True)

    CASE_A = auto()
    CASE_B = auto()

or (as there is no nonmember in <3.11):

class AwesomeEnum(Enum):
    @property
    def do_not_call_in_templates(self):
        return True

    CASE_A = auto()
    CASE_B = auto()

Maybe this is can be implemented as a nice little ruff rule? We just noticed this after having a do_not_call_in_templates member in our enum for nearly 4 years :smile:

Kakadus avatar Oct 28 '24 21:10 Kakadus