11# Copyright 2016, Yahoo Inc.
22# Licensed under the terms of the Apache License, Version 2.0. See the LICENSE file associated with the project for terms.
3- import contextlib
43import logging
54from collections import namedtuple
65
1514log = logging .getLogger (__name__ )
1615
1716
18- @contextlib .contextmanager
19- ## def jetsam(locs, *salvage_vars, annotation="graphkit_jetsam", **salvage_mappings): # bad PY2 syntax
20- def jetsam (locs , * salvage_vars , ** salvage_mappings ):
17+ ## def jetsam(ex, locs, *salvage_vars, annotation="graphkit_jetsam", **salvage_mappings): # bad PY2 syntax
18+ def jetsam (ex , locs , * salvage_vars , ** salvage_mappings ):
2119 """
22- Debug-aid to annotate exceptions with salvaged values from wrapped functions .
20+ Annotate exception with salvaged values from locals() .
2321
22+ :param ex:
23+ the exception to annotate
2424 :param locs:
2525 ``locals()`` from the context-manager's block containing vars
2626 to be salvaged in case of exception
2727
2828 ATTENTION: wrapped function must finally call ``locals()``, because
2929 *locals* dictionary only reflects local-var changes after call.
30+ :param str annotation:
31+ (a kwarg not seen in the signature due to PY2 compatibility)
32+ the name of the attribute to attach on the exception
3033 :param salvage_vars:
3134 local variable names to save as is in the salvaged annotations dictionary.
3235 :param salvage_mappings:
@@ -50,21 +53,19 @@ def jetsam(locs, *salvage_vars, **salvage_mappings):
5053 in case of errors::
5154
5255
53- with jetsam(locals(), "a", b="salvaged_b", c_var="c"):
54- try:
55- a = 1
56- b = 2
57- raise Exception()
58- finally:
59- locals() # to update locals-dict handed to jetsam().
56+ try:
57+ a = 1
58+ b = 2
59+ raise Exception()
60+ exception Exception as ex:
61+ jetsam(ex, locals(), "a", b="salvaged_b", c_var="c")
6062
6163 And then from a REPL::
6264
6365 import sys
6466 sys.last_value.graphkit_jetsam
6567 {'a': 1, 'salvaged_b': 2, "c_var": None}
6668
67-
6869 ** Reason:**
6970
7071 Graphs may become arbitrary deep. Debugging such graphs is notoriously hard.
@@ -80,6 +81,7 @@ def jetsam(locs, *salvage_vars, **salvage_mappings):
8081 #
8182 annotation = salvage_mappings .pop ("annotation" , "graphkit_jetsam" )
8283
84+ assert isinstance (ex , Exception ), ("Bad `ex`, not an exception dict:" , ex )
8385 assert isinstance (locs , dict ), ("Bad `locs`, not a dict:" , locs )
8486 assert all (isinstance (i , str ) for i in salvage_vars ), (
8587 "Bad `salvage_vars`!" ,
@@ -97,30 +99,26 @@ def jetsam(locs, *salvage_vars, **salvage_mappings):
9799 salvage_mappings [var ] = var
98100
99101 try :
100- yield jetsam
101- except Exception as ex_to_annotate :
102- try :
103- annotations = getattr (ex_to_annotate , annotation , None )
104- if not isinstance (annotations , dict ):
105- annotations = {}
106- setattr (ex_to_annotate , annotation , annotations )
107-
108- ## Salvage those asked
109- for dst_key , src in salvage_mappings .items ():
110- try :
111- salvaged_value = src (locs ) if callable (src ) else locs .get (src )
112- annotations .setdefault (dst_key , salvaged_value )
113- except Exception as ex :
114- log .warning (
115- "Supressed error while salvaging jetsam item (%r, %r): %r"
116- % (dst_key , src , ex )
117- )
118- except Exception as ex :
119- log .warning (
120- "Supressed error while annotating exception: %r" , ex , exc_info = 1
121- )
102+ annotations = getattr (ex , annotation , None )
103+ if not isinstance (annotations , dict ):
104+ annotations = {}
105+ setattr (ex , annotation , annotations )
122106
123- raise # re-raise without ex-arg, not to insert my frame
107+ ## Salvage those asked
108+ for dst_key , src in salvage_mappings .items ():
109+ try :
110+ salvaged_value = src (locs ) if callable (src ) else locs .get (src )
111+ annotations .setdefault (dst_key , salvaged_value )
112+ except Exception as ex :
113+ log .warning (
114+ "Supressed error while salvaging jetsam item (%r, %r): %r"
115+ % (dst_key , src , ex )
116+ )
117+ except Exception as ex2 :
118+ log .warning ("Supressed error while annotating exception: %r" , ex2 , exc_info = 1 )
119+ raise ex2
120+
121+ raise # noqa #re-raise without ex-arg, not to insert my frame
124122
125123
126124class Data (object ):
@@ -214,23 +212,22 @@ def compute(self, inputs):
214212 raise NotImplementedError ("Define callable of %r!" % self )
215213
216214 def _compute (self , named_inputs , outputs = None ):
217- with jetsam (
218- locals (), "outputs" , "provides" , "args" , "results" , operation = "self"
219- ):
220- try :
221- provides = self .provides
222- args = [named_inputs [d ] for d in self .needs ]
223- results = self .compute (args )
215+ try :
216+ provides = self .provides
217+ args = [named_inputs [d ] for d in self .needs ]
218+ results = self .compute (args )
224219
225- results = zip (provides , results )
220+ results = zip (provides , results )
226221
227- if outputs :
228- outs = set (outputs )
229- results = filter (lambda x : x [0 ] in outs , results )
222+ if outputs :
223+ outs = set (outputs )
224+ results = filter (lambda x : x [0 ] in outs , results )
230225
231- return dict (results )
232- finally :
233- locals () # to update locals-dict handed to jetsam()
226+ return dict (results )
227+ except Exception as ex :
228+ jetsam (
229+ ex , locals (), "outputs" , "provides" , "args" , "results" , operation = "self"
230+ )
234231
235232 def _after_init (self ):
236233 """
0 commit comments