-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathmapping.py
More file actions
executable file
·103 lines (70 loc) · 3.02 KB
/
Copy pathmapping.py
File metadata and controls
executable file
·103 lines (70 loc) · 3.02 KB
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
from typing import List, Tuple, Callable, Any
from .base import ILoaderClass, Loader, CAPTURE_EXCEPTIONS
from .exception import CompositeStructureError
from .types import method
from .utils import raw
MAPPING_ERROR_ITEM = Tuple[str, Exception]
MAPPING_ERRORS = List[MAPPING_ERROR_ITEM]
class MappingError(CompositeStructureError):
def __init__(self, key_errors: MAPPING_ERRORS, value_errors: MAPPING_ERRORS):
self.__key_errors = list(key_errors or [])
self.__value_errors = list(value_errors or [])
self.__errors = self.__key_errors + self.__value_errors
def key_errors(self) -> MAPPING_ERRORS:
return self.__key_errors
def value_errors(self) -> MAPPING_ERRORS:
return self.__value_errors
def errors(self) -> MAPPING_ERRORS:
return self.__errors
def mapping(key_loader, value_loader, type_back: bool = True) -> ILoaderClass:
key_loader = Loader(key_loader)
value_loader = Loader(value_loader)
def _load(value):
_key_errors = []
_value_errors = []
_result = {}
for key_, value_ in value.items():
key_error, value_error = None, None
key_result, value_result = None, None
try:
key_result = key_loader(key_)
except CAPTURE_EXCEPTIONS as err:
key_error = err
try:
value_result = value_loader(value_)
except CAPTURE_EXCEPTIONS as err:
value_error = err
if not key_error and not value_error:
_result[key_result] = value_result
else:
if key_error:
_key_errors.append((key_, key_error))
if value_error:
_value_errors.append((key_, value_error))
if not _key_errors and not _value_errors:
if type_back:
_result = type(value)(_result)
return _result
else:
raise MappingError(_key_errors, _value_errors)
return method('items') & Loader(_load)
def mpfilter(check: Callable[[Any, Any], bool], type_back: bool = True) -> ILoaderClass:
def _load(value):
_result = {key_: value_ for key_, value_ in value.items() if check(key_, value_)}
if type_back:
_result = type(value)(_result)
return _result
return method('items') & Loader(_load)
def mpkeys() -> ILoaderClass:
return method('items') & method('keys') & Loader(lambda v: set(v.keys()))
def mpvalues() -> ILoaderClass:
return method('items') & method('values') & Loader(lambda v: set(v.values()))
def mpitems() -> ILoaderClass:
return method('items') & Loader(lambda v: set([(key, value) for key, value in v.items()]))
_INDEX_PRECHECK = method('__getitem__')
def item(key) -> ILoaderClass:
return _INDEX_PRECHECK & Loader(
(lambda v: key in v.keys(), lambda v: v[key], KeyError('key {key} not found'.format(key=repr(key))))
)
def item_or(key, default) -> ILoaderClass:
return _INDEX_PRECHECK & (item(key) | raw(default))