-
Notifications
You must be signed in to change notification settings - Fork 0
/
rec_get.py
57 lines (46 loc) · 1.78 KB
/
rec_get.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
"""
Implements function for chained access of dictionaries and lists.
Has additional functionality of throwing exception recursively to document key or index access error during access.
"""
def rec_get(data, *args):
assert len(args) > 0, "At least one key or index must be supplied"
try:
if len(args) == 1:
return data[args[0]]
else:
return rec_get(data[args[0]], *args[1:])
except (KeyError, IndexError, TypeError) as e:
raise ParsingKeyError(key=args[0], reason_err=e)
except ParsingKeyError as parsing_key_error:
raise ParsingKeyError(key=args[0], parsing_key_error=parsing_key_error)
class ParsingKeyError(Exception):
def __init__(self, key, reason_err=None, parsing_key_error=None):
self.loc = [key]
if parsing_key_error is None:
self.reason = f'{type(reason_err).__name__}: {str(reason_err)}'
else:
self.loc.extend(parsing_key_error.loc)
self.reason = parsing_key_error.reason
self.str_loc = self.generate_str_location(self.loc)
self.msg = f"Couldn't access using key or index @ {self.str_loc}. Reason: {self.reason}"
@staticmethod
def generate_str_location(location):
msg = list()
for part in location:
if type(part) == int:
msg.append(f'(index) {part}')
else:
msg.append(f'(key) {str(part)}')
return ': '.join(msg)
if __name__ == "__main__":
d = {'a': ['a0', 'a1', 'a2', 'a3'],
'b': {'b0': ['b00', 'b01', 'b02'], 'b1': 'text'}}
print(rec_get(d, 'b', 'b0', 1))
try:
rec_get(d, 'a', 4)
except ParsingKeyError as pke:
print(pke.msg)
try:
rec_get(d, 'b', 'b2')
except ParsingKeyError as pke:
print(pke.msg)