Coverage for audoma/choices.py: 69%

16 statements  

« prev     ^ index     » next       coverage.py v6.4.2, created at 2022-08-04 07:22 +0000

1from typing import ( 

2 Any, 

3 List, 

4 Tuple, 

5 TypeVar, 

6) 

7 

8 

9_T = TypeVar("_T") 

10 

11 

12def make_choices(name: str, choices_tuple: Tuple[Any, str, str]) -> _T: 

13 from collections import namedtuple 

14 

15 """Factory function for quickly making a namedtuple suitable for use in a 

16 Django model as a choices attribute on a field. It will preserve order. 

17 

18 Usage:: 

19 

20 class MyModel(models.Model): 

21 COLORS = make_choices('COLORS', ( 

22 (0, 'BLACK', 'Black'), 

23 (1, 'WHITE', 'White'), 

24 )) 

25 colors = models.PositiveIntegerField(choices=COLORS) 

26 

27 >>> MyModel.COLORS.BLACK 

28 0 

29 >>> MyModel.COLORS.get_choices() 

30 [(0, 'Black'), (1, 'White')] 

31 

32 class OtherModel(models.Model): 

33 GRADES = make_choices('GRADES', ( 

34 ('FR', 'FR', 'Freshman'), 

35 ('SR', 'SR', 'Senior'), 

36 )) 

37 grade = models.CharField(max_length=2, choices=GRADES) 

38 

39 >>> OtherModel.GRADES.FR 

40 'FR' 

41 >>> OtherModel.GRADES.get_choices() 

42 [('FR', 'Freshman'), ('SR', 'Senior')] 

43 

44 """ 

45 

46 class Choices(namedtuple(name, [name_ for val, name_, desc in choices_tuple])): 

47 __slots__ = () 

48 _choices = tuple([desc for val, name_, desc in choices_tuple]) 

49 

50 def get_display(self, val: Any) -> str: 

51 return self._choices[self.index(val)] 

52 

53 def get_choices(self) -> List[Tuple[Any, str]]: 

54 return list(zip(tuple(self), self._choices)) 

55 

56 def get_api_choices(self) -> List[Tuple[str, str]]: 

57 return list(zip(tuple(self._asdict()), tuple(self._choices))) 

58 

59 def get_value_by_name(self, name: str) -> Any: 

60 return getattr(self, name) 

61 

62 return Choices._make([val for val, name_, desc in choices_tuple])