-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
formatters.py
134 lines (107 loc) · 3.18 KB
/
formatters.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
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
from collections.abc import (
Mapping,
)
from typing import (
Any,
Callable,
Dict,
Iterable,
Sequence,
Tuple,
TypeVar,
)
from eth_typing import (
HexStr,
)
from eth_utils import (
is_dict,
is_list_like,
is_string,
to_dict,
to_list,
)
from eth_utils.curried import (
apply_formatter_at_index,
)
from eth_utils.toolz import (
compose,
curry,
dissoc,
)
from web3._utils.decorators import (
reject_recursive_repeats,
)
TReturn = TypeVar("TReturn")
TValue = TypeVar("TValue")
def hex_to_integer(value: HexStr) -> int:
return int(value, 16)
integer_to_hex = hex
def apply_formatters_to_args(*formatters: Callable[[TValue], TReturn]) -> Callable[..., TReturn]:
return compose(*(
apply_formatter_at_index(formatter, index)
for index, formatter
in enumerate(formatters)
))
@curry
@to_list
def apply_formatter_to_array(
formatter: Callable[[TValue], TReturn], value: Sequence[TValue]
) -> Iterable[TReturn]:
for item in value:
yield formatter(item)
def map_collection(func: Callable[..., TReturn], collection: Any) -> Any:
"""
Apply func to each element of a collection, or value of a dictionary.
If the value is not a collection, return it unmodified
"""
datatype = type(collection)
if isinstance(collection, Mapping):
return datatype((key, func(val)) for key, val in collection.items())
if is_string(collection):
return collection
elif isinstance(collection, Iterable):
return datatype(map(func, collection))
else:
return collection
@reject_recursive_repeats
def recursive_map(func: Callable[..., TReturn], data: Any) -> TReturn:
"""
Apply func to data, and any collection items inside data (using map_collection).
Define func so that it only applies to the type of value that you want it to apply to.
"""
def recurse(item: Any) -> TReturn:
return recursive_map(func, item)
items_mapped = map_collection(recurse, data)
return func(items_mapped)
def static_return(value: TValue) -> Callable[..., TValue]:
def inner(*args: Any, **kwargs: Any) -> TValue:
return value
return inner
def static_result(value: TValue) -> Callable[..., Dict[str, TValue]]:
def inner(*args: Any, **kwargs: Any) -> Dict[str, TValue]:
return {'result': value}
return inner
@curry
@to_dict
def apply_key_map(key_mappings: Dict[Any, Any], value: Dict[Any, Any]) -> Iterable[Tuple[Any, Any]]:
for key, item in value.items():
if key in key_mappings:
yield key_mappings[key], item
else:
yield key, item
def is_array_of_strings(value: Any) -> bool:
if not is_list_like(value):
return False
return all((is_string(item) for item in value))
def is_array_of_dicts(value: Any) -> bool:
if not is_list_like(value):
return False
return all((is_dict(item) for item in value))
@curry
def remove_key_if(
key: Any, remove_if: Callable[[Dict[Any, Any]], bool], input_dict: Dict[Any, Any]
) -> Dict[Any, Any]:
if key in input_dict and remove_if(input_dict):
return dissoc(input_dict, key)
else:
return input_dict