1
- '''
1
+ """
2
2
Utility functions for use in function pipelines.
3
- '''
3
+ """
4
4
import functools
5
5
import typing as tp
6
6
15
15
16
16
17
17
def node (_func = None , * , name = None ):
18
- ''' Turn the decorated function into a MetaFunction.
18
+ """ Turn the decorated function into a MetaFunction.
19
19
20
20
Args:
21
21
_func: Internal use. This will be the decorated function if node is used as a decorator
@@ -26,10 +26,12 @@ def node(_func=None, *, name=None):
26
26
@node
27
27
def f(x):
28
28
<do something cool>
29
- '''
29
+ """
30
+
30
31
def decorator (function ):
31
32
newfunc = SimpleFunction (function , name = name )
32
33
return newfunc
34
+
33
35
if not _func :
34
36
return decorator
35
37
return decorator (_func )
@@ -38,50 +40,60 @@ def decorator(function):
38
40
def bind_call_state (func ):
39
41
@functools .wraps (func )
40
42
def provides_call_state (* args , ** kwargs ):
41
- call_state = kwargs .pop (' call_state' )
43
+ call_state = kwargs .pop (" call_state" )
42
44
return func (call_state , * args , ** kwargs )
45
+
43
46
provides_call_state ._receives_call_state = True
44
47
return provides_call_state
45
48
46
49
47
50
def star (meta_function : MetaFunction ) -> MetaFunction :
48
- '''
51
+ """
49
52
star calls its Metafunction with *x instead of x.
50
- '''
53
+ """
51
54
fname = str (meta_function )
52
- #This convoluted inline `if` just decides whether we should add brackets or not.
53
- @node (name = 'star{}' .format (fname ) if fname .startswith ('(' ) else 'star({})' .format (fname ))
55
+ # This convoluted inline `if` just decides whether we should add brackets or not.
56
+ @node (
57
+ name = "star{}" .format (fname )
58
+ if fname .startswith ("(" )
59
+ else "star({})" .format (fname )
60
+ )
54
61
@functools .wraps (meta_function )
55
62
def wrapper (args , ** kwargs ):
56
63
return meta_function (* args , ** kwargs )
64
+
57
65
return wrapper
58
66
59
67
60
68
def store (key ):
61
- '''Store the received output in the meta data dictionary under the given key.'''
69
+ """Store the received output in the meta data dictionary under the given key."""
70
+
62
71
@node (name = "store('{}')" .format (key ))
63
72
@bind_call_state
64
73
def storer (call_state , val ):
65
74
call_state .data [key ] = val
66
75
return val
76
+
67
77
return storer
68
78
69
79
70
- def recall (key , from_call_state : CallState = None ):
71
- ''' Retrieve the given key from the meta data dictionary. Optionally, use `from_call_state` to
80
+ def recall (key , from_call_state : CallState = None ):
81
+ """ Retrieve the given key from the meta data dictionary. Optionally, use `from_call_state` to
72
82
specify a different call_state than the current one.
73
- '''
83
+ """
84
+
74
85
@node (name = "recall('{}')" .format (key ))
75
86
@bind_call_state
76
87
def recaller (call_state , * _ ):
77
88
if from_call_state :
78
89
return from_call_state .data [key ]
79
90
return call_state .data [key ]
91
+
80
92
return recaller
81
93
82
94
83
95
def concurrent (function : FunctionMerge ) -> ConcurrentMerge :
84
- '''
96
+ """
85
97
Upgrade the specified FunctionMerge object to a ConcurrentMerge, which runs each of its
86
98
component functions in separate processes. See ConcurrentMerge documentation for more
87
99
information.
@@ -90,46 +102,51 @@ def concurrent(function: FunctionMerge) -> ConcurrentMerge:
90
102
91
103
c = concurrent(long_running_function + other_long_running_function)
92
104
c(input_data) # The two functions run in parallel
93
- '''
105
+ """
94
106
return ConcurrentMerge (function )
95
107
96
108
97
- def mmap (function : tp .Callable , operator : tp .Callable = operators .concat ) -> MergeMap :
98
- '''
109
+ def mmap (function : tp .Callable , operator : tp .Callable = operators .concat ) -> MergeMap :
110
+ """
99
111
Upgrade the specified function to a MergeMap, which calls its single function once per input,
100
112
as per the builtin `map` (https://docs.python.org/3.6/library/functions.html#map).
101
113
102
114
Consider the name 'mmap' to be a placeholder for now.
103
- '''
115
+ """
104
116
return MergeMap (MetaFunction .make_meta (function ), operator )
105
117
106
118
107
- def locate_error (meta_function : MetaFunction ,
108
- use_color = util .system_supports_color ()) -> SimpleFunction :
109
- '''
119
+ def locate_error (
120
+ meta_function : MetaFunction , use_color = util .system_supports_color ()
121
+ ) -> SimpleFunction :
122
+ """
110
123
Wrap the given MetaFunction with an error handler that adds location information to any
111
124
exception raised therein.
112
125
113
126
Usage:
114
127
cmp = locate_error(a | b | c)
115
128
cmp()
116
- '''
129
+ """
130
+
117
131
def with_location (* args , call_state , ** kwargs ):
118
132
new_e = None
119
133
try :
120
134
return meta_function (* args , call_state = call_state , ** kwargs )
121
135
except Exception as e :
122
- if hasattr (e , ' location' ) and e .location :
136
+ if hasattr (e , " location" ) and e .location :
123
137
# If the exception has location info attached
124
138
location = e .location
125
139
else :
126
140
location = call_state .highlight_active_function ()
127
141
128
142
if use_color :
129
143
location = util .color_highlights (location )
130
- detailed_message = ("{0!s} \n \n Occured in the following function: {1}" .format (e , location ))
144
+ detailed_message = (
145
+ "{0!s} \n \n Occured in the following function: {1}" .format (e , location )
146
+ )
131
147
new_e = type (e )(detailed_message ).with_traceback (e .__traceback__ )
132
148
new_e .__cause__ = e .__cause__
133
149
raise new_e
150
+
134
151
with_location ._receives_call_state = True
135
152
return node (with_location , name = str (meta_function ))
0 commit comments