-
Notifications
You must be signed in to change notification settings - Fork 0
/
pyf.py
133 lines (84 loc) · 2.17 KB
/
pyf.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
import builtins
import functools
import inspect
from pipe import Pipe
__all__ = [
'identity', 'always', 'as_str', 'as_int', 'prop', 'values', 'prepend',
'merge', 'path', 'map', 'filter', 'reduce', 'pick', 'omit', 'equals',
'prop_eq', 'find', 'find_index', 'partial'
]
def partial(f):
@functools.wraps(f)
def wrapped(*args, **kwargs):
func = functools.partial(f, *args, **kwargs)
arity = len(inspect.getfullargspec(func).args)
return func if arity else func()
return wrapped
def identity(x):
return x
def always(x):
return lambda: x
@Pipe
def as_str(x) -> str:
return str(x)
@Pipe
def as_int(x) -> int:
return int(x)
@partial
def equals(x, y) -> bool:
return x == y
@partial
def prop_eq(k, v, dct):
return equals(v, dct[k])
@Pipe
def prop(dct: dict, k: str, default=None):
return dct.get(k, default)
@Pipe
def values(dct: dict) -> list:
return list(dct.values())
@Pipe
def prepend(lst: list, elm) -> list:
return [elm] + lst
@Pipe
def merge(l_dct: dict, r_dct: dict) -> dict:
return {**l_dct, **r_dct}
@Pipe
def path(dct: dict, steps: list, default=None):
k = steps[0]
v = dct.get(k, default) if isinstance(dct, dict) else default
t = steps[1:]
return v if not t else v | path(t, default)
@Pipe
def map(lst: list, f: callable):
return builtins.map(f, lst)
@Pipe
def filter(lst, f: callable):
return builtins.filter(f, lst)
@Pipe
def reduce(lst: list, f: callable, init=None):
if init is None:
init, *lst = lst
return functools.reduce(f, lst, init)
@Pipe
def pick(dct: dict, names: list) -> dict:
return {k: v for k, v in dct.items() if k in names}
@Pipe
def omit(dct: dict, names: list) -> dict:
return {k: v for k, v in dct.items() if k not in names}
@Pipe
def find(lst: list, f: callable):
v = next(iter(lst), None)
if v is None:
return None
if f(v):
return v
return lst[1:] | find(f)
@Pipe
def find_index(lst: list, f: callable):
for k, v in enumerate(lst):
if f(v):
return k
return -1
if __name__ == '__main__':
import doctest
doctest.testfile('README.md', verbose=True)