a metaclass for creating a enum choices def newmetacls classname bases classdict kwds labels for key in classdict membernames value classdictkey if isinstancevalue list tuple and lenvalue 1 and isinstancevalue1 promise str value label value value tuplevalue else label key replace title labels appendlabel use dict setitem to suppress defenses against double assignment in enum s classdict dict setitemclassdict key value cls super newmetacls classname bases classdict kwds for member label in zipcls members values labels member label label return enum uniquecls if not py312 def containscls member if not isinstancemember enum enum allow nonenums to match against member values return anyx value member for x in cls return super containsmember property def namescls empty empty if hasattrcls empty else return empty member name for member in cls property def choicescls empty none cls empty if hasattrcls empty else return empty member value member label for member in cls property def labelscls return label for label in cls choices property def valuescls return value for value in cls choices class choicesenum enum metaclasschoicestype a similar format was proposed for python 3 10 class for creating enumerated integer choices pass class textchoiceschoices strenum a metaclass for creating a enum choices use dict __setitem__ to suppress defenses against double assignment in enum s classdict allow non enums to match against member values class for creating enumerated choices a similar format was proposed for python 3 10 class for creating enumerated integer choices class for creating enumerated string choices
import enum
import warnings

from django.utils.deprecation import RemovedInDjango60Warning
from django.utils.functional import Promise
from django.utils.version import PY311, PY312

if PY311:
    from enum import EnumType, IntEnum, StrEnum
    from enum import property as enum_property
else:
    from enum import EnumMeta as EnumType
    from types import DynamicClassAttribute as enum_property

    class ReprEnum(enum.Enum):
        def __str__(self):
            return str(self.value)

    class IntEnum(int, ReprEnum):
        pass

    class StrEnum(str, ReprEnum):
        pass


__all__ = ["Choices", "IntegerChoices", "TextChoices"]


class ChoicesType(EnumType):
    

    def __new__(metacls, classname, bases, classdict, **kwds):
        labels = []
        for key in classdict._member_names:
            value = classdict[key]
            if (
                isinstance(value, (list, tuple))
                and len(value) > 1
                and isinstance(value[-1], (Promise, str))
            ):
                *value, label = value
                value = tuple(value)
            else:
                label = key.replace("_", " ").title()
            labels.append(label)
            
            
            dict.__setitem__(classdict, key, value)
        cls = super().__new__(metacls, classname, bases, classdict, **kwds)
        for member, label in zip(cls.__members__.values(), labels):
            member._label_ = label
        return enum.unique(cls)

    if not PY312:

        def __contains__(cls, member):
            if not isinstance(member, enum.Enum):
                
                return any(x.value == member for x in cls)
            return super().__contains__(member)

    @property
    def names(cls):
        empty = ["__empty__"] if hasattr(cls, "__empty__") else []
        return empty + [member.name for member in cls]

    @property
    def choices(cls):
        empty = [(None, cls.__empty__)] if hasattr(cls, "__empty__") else []
        return empty + [(member.value, member.label) for member in cls]

    @property
    def labels(cls):
        return [label for _, label in cls.choices]

    @property
    def values(cls):
        return [value for value, _ in cls.choices]


class Choices(enum.Enum, metaclass=ChoicesType):
    

    if PY311:
        do_not_call_in_templates = enum.nonmember(True)
    else:

        @property
        def do_not_call_in_templates(self):
            return True

    @enum_property
    def label(self):
        return self._label_

    
    def __repr__(self):
        return f"{self.__class__.__qualname__}.{self._name_}"


class IntegerChoices(Choices, IntEnum):
    

    pass


class TextChoices(Choices, StrEnum):
    

    @staticmethod
    def _generate_next_value_(name, start, count, last_values):
        return name


def __getattr__(name):
    if name == "ChoicesMeta":
        warnings.warn(
            "ChoicesMeta is deprecated in favor of ChoicesType.",
            RemovedInDjango60Warning,
            stacklevel=2,
        )
        return ChoicesType
    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")