Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.10/site-packages/django/db/models/enums.py: 61%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

67 statements  

1import enum 

2 

3from django.utils.functional import Promise 

4from django.utils.version import PY311, PY312 

5 

6if PY311: 

7 from enum import EnumType, IntEnum, StrEnum 

8 from enum import property as enum_property 

9else: 

10 from enum import EnumMeta as EnumType 

11 from types import DynamicClassAttribute as enum_property 

12 

13 class ReprEnum(enum.Enum): 

14 def __str__(self): 

15 return str(self.value) 

16 

17 class IntEnum(int, ReprEnum): 

18 pass 

19 

20 class StrEnum(str, ReprEnum): 

21 pass 

22 

23 

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

25 

26 

27class ChoicesType(EnumType): 

28 """A metaclass for creating a enum choices.""" 

29 

30 def __new__(metacls, classname, bases, classdict, **kwds): 

31 labels = [] 

32 for key in classdict._member_names: 

33 value = classdict[key] 

34 if ( 

35 isinstance(value, (list, tuple)) 

36 and len(value) > 1 

37 and isinstance(value[-1], (Promise, str)) 

38 ): 

39 *value, label = value 

40 value = tuple(value) 

41 else: 

42 label = key.replace("_", " ").title() 

43 labels.append(label) 

44 # Use dict.__setitem__() to suppress defenses against double 

45 # assignment in enum's classdict. 

46 dict.__setitem__(classdict, key, value) 

47 cls = super().__new__(metacls, classname, bases, classdict, **kwds) 

48 for member, label in zip(cls.__members__.values(), labels): 

49 member._label_ = label 

50 return enum.unique(cls) 

51 

52 if not PY312: 

53 

54 def __contains__(cls, member): 

55 if not isinstance(member, enum.Enum): 

56 # Allow non-enums to match against member values. 

57 return any(x.value == member for x in cls) 

58 return super().__contains__(member) 

59 

60 @property 

61 def names(cls): 

62 empty = ["__empty__"] if hasattr(cls, "__empty__") else [] 

63 return empty + [member.name for member in cls] 

64 

65 @property 

66 def choices(cls): 

67 empty = [(None, cls.__empty__)] if hasattr(cls, "__empty__") else [] 

68 return empty + [(member.value, member.label) for member in cls] 

69 

70 @property 

71 def labels(cls): 

72 return [label for _, label in cls.choices] 

73 

74 @property 

75 def values(cls): 

76 return [value for value, _ in cls.choices] 

77 

78 

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

80 """Class for creating enumerated choices.""" 

81 

82 if PY311: 

83 do_not_call_in_templates = enum.nonmember(True) 

84 else: 

85 

86 @property 

87 def do_not_call_in_templates(self): 

88 return True 

89 

90 @enum_property 

91 def label(self): 

92 return self._label_ 

93 

94 # A similar format was proposed for Python 3.10. 

95 def __repr__(self): 

96 return f"{self.__class__.__qualname__}.{self._name_}" 

97 

98 

99class IntegerChoices(Choices, IntEnum): 

100 """Class for creating enumerated integer choices.""" 

101 

102 pass 

103 

104 

105class TextChoices(Choices, StrEnum): 

106 """Class for creating enumerated string choices.""" 

107 

108 @staticmethod 

109 def _generate_next_value_(name, start, count, last_values): 

110 return name