Coverage for casanova/casanova/namedrecord.py: 98%

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

52 statements  

1# ============================================================================= 

2# Casanova Named Record Helper 

3# ============================================================================= 

4# 

5# CSV-aware improvement over python's namedtuple. 

6# 

7from json import dumps 

8from collections import OrderedDict 

9 

10from casanova._namedtuple import future_namedtuple 

11 

12 

13def namedrecord(name, fields, boolean=None, plural=None, json=None, defaults=None): 

14 mapping = {k: i for i, k in enumerate(fields)} 

15 mask = [] 

16 

17 for k in fields: 

18 if boolean and k in boolean: 

19 mask.append(1) 

20 elif plural and k in plural: 

21 mask.append(2) 

22 elif json and k in json: 

23 mask.append(3) 

24 else: 

25 mask.append(0) 

26 

27 def cast_for_csv(i, v, plural_separator='|'): 

28 if v is None: 

29 return None 

30 

31 m = mask[i] 

32 

33 if m == 0: 

34 return v 

35 

36 if m == 1: 

37 return 'true' if v else 'false' 

38 

39 if m == 2: 

40 assert isinstance(v, list) 

41 return plural_separator.join(str(i) for i in v) 

42 

43 if m == 3: 

44 return dumps(v, ensure_ascii=False) 

45 

46 raise TypeError 

47 

48 class Record(future_namedtuple(name, fields, defaults=defaults)): 

49 def __getitem__(self, key): 

50 if isinstance(key, str): 

51 idx = mapping.get(key) 

52 

53 if idx is None: 

54 raise KeyError 

55 

56 return super().__getitem__(idx) 

57 

58 return super().__getitem__(key) 

59 

60 def get(self, key, default=None): 

61 try: 

62 return self.__getitem__(key) 

63 except (IndexError, KeyError): 

64 return default 

65 

66 def as_csv_row(self, plural_separator='|'): 

67 row = list( 

68 cast_for_csv(i, v, plural_separator=plural_separator) 

69 for i, v in enumerate(self) 

70 ) 

71 

72 return row 

73 

74 def as_csv_dict_row(self, plural_separator='|'): 

75 row = OrderedDict( 

76 (fields[i], cast_for_csv(i, v, plural_separator=plural_separator)) 

77 for i, v in enumerate(self) 

78 ) 

79 

80 return row 

81 

82 def as_dict(self): 

83 return {fields[i]: v for i, v in enumerate(self)} 

84 

85 Record.__name__ = name 

86 Record.fieldnames = list(fields) 

87 

88 return Record