1+ import traceback
12from functools import reduce
23
34from effect import Constant , Effect
45
56
7+ class FoldError (Exception ):
8+ """
9+ Raised when one of the Effects passed to :func:`fold_effect` fails.
10+
11+ :ivar accumulator: The data accumulated so far, before the failing Effect.
12+ :ivar wrapped_exception: The exc_info tuple representing the original
13+ exception raised by the failing Effect.
14+ """
15+ def __init__ (self , accumulator , wrapped_exception ):
16+ self .accumulator = accumulator
17+ self .wrapped_exception = wrapped_exception
18+
19+ def __str__ (self ):
20+ tb_lines = traceback .format_tb (self .wrapped_exception [2 ])
21+ tb = '' .join (tb_lines )
22+ return "FoldError(%r, %r) -> ORIGINAL TRACEBACK FOLLOWS\n %s" % (
23+ self .accumulator , self .wrapped_exception , tb )
24+
25+
626def fold_effect (f , initial , effects ):
727 """
828 Fold over effects.
@@ -18,8 +38,12 @@ def fold_effect(f, initial, effects):
1838 :param effects: sequence of Effects.
1939 """
2040
41+ def failed (acc , e ):
42+ raise FoldError (acc , e )
43+
2144 def folder (acc , element ):
22- return acc .on (lambda r : element .on (lambda r2 : f (r , r2 )))
45+ return acc .on (lambda r : element .on (lambda r2 : f (r , r2 ),
46+ error = lambda e : failed (r , e )))
2347
2448 return reduce (folder , effects , Effect (Constant (initial )))
2549
0 commit comments