Coverage for casanova/casanova/namedrecord.py: 46%
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
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
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
10from casanova._namedtuple import future_namedtuple
13def namedrecord(name, fields, boolean=None, plural=None, json=None, defaults=None):
14 mapping = {k: i for i, k in enumerate(fields)}
15 mask = []
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)
27 def cast_for_csv(i, v, plural_separator='|'):
28 if v is None:
29 return None
31 m = mask[i]
33 if m == 0:
34 return v
36 if m == 1:
37 return 'true' if v else 'false'
39 if m == 2:
40 assert isinstance(v, list)
41 return plural_separator.join(str(i) for i in v)
43 if m == 3:
44 return dumps(v, ensure_ascii=False)
46 raise TypeError
48 class Record(future_namedtuple(name, fields, defaults=defaults)):
49 def __getitem__(self, key):
50 if isinstance(key, str):
51 idx = mapping.get(key)
53 if idx is None:
54 raise KeyError
56 return super().__getitem__(idx)
58 return super().__getitem__(key)
60 def get(self, key, default=None):
61 try:
62 return self.__getitem__(key)
63 except (IndexError, KeyError):
64 return default
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 )
72 return row
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 )
80 return row
82 def as_dict(self):
83 return {fields[i]: v for i, v in enumerate(self)}
85 Record.__name__ = name
86 Record.fieldnames = list(fields)
88 return Record