Skip to content

Commit 618bcef

Browse files
author
Philip Guo
committed
beautiful further fix to show parent frames of
functions nested within data structures (by John DeNero)
1 parent 6e26f91 commit 618bcef

6 files changed

Lines changed: 28 additions & 43 deletions

File tree

v3/example-code/closures/student-torture.golden_py3

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@
460460
"5": [
461461
"FUNCTION",
462462
"<lambda>()",
463-
null
463+
2
464464
]
465465
},
466466
"line": 10,
@@ -699,7 +699,7 @@
699699
"7": [
700700
"FUNCTION",
701701
"<lambda>()",
702-
null
702+
1
703703
]
704704
},
705705
"line": 12,

v3/pg_encoder.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ def set_function_parent_frame_ID(self, ref_obj, enclosing_frame_id):
122122

123123
# return either a primitive object or an object reference;
124124
# and as a side effect, update encoded_heap_objects
125-
def encode(self, dat):
125+
def encode(self, dat, get_parent):
126+
"""Encode a data value DAT using the GET_PARENT function for parent ids."""
126127
# primitive type
127128
if type(dat) in (int, long, float, str, bool, type(None)):
128129
if type(dat) is float:
@@ -159,21 +160,21 @@ def encode(self, dat):
159160
if typ == list:
160161
new_obj.append('LIST')
161162
for e in dat:
162-
new_obj.append(self.encode(e))
163+
new_obj.append(self.encode(e, get_parent))
163164
elif typ == tuple:
164165
new_obj.append('TUPLE')
165166
for e in dat:
166-
new_obj.append(self.encode(e))
167+
new_obj.append(self.encode(e, get_parent))
167168
elif typ == set:
168169
new_obj.append('SET')
169170
for e in dat:
170-
new_obj.append(self.encode(e))
171+
new_obj.append(self.encode(e, get_parent))
171172
elif typ == dict:
172173
new_obj.append('DICT')
173174
for (k, v) in dat.items():
174175
# don't display some built-in locals ...
175176
if k not in ('__module__', '__return__', '__locals__'):
176-
new_obj.append([self.encode(k), self.encode(v)])
177+
new_obj.append([self.encode(k, get_parent), self.encode(v, get_parent)])
177178
elif typ in (types.FunctionType, types.MethodType):
178179
if is_python3:
179180
argspec = inspect.getfullargspec(dat)
@@ -195,7 +196,11 @@ def encode(self, dat):
195196

196197
func_name = get_name(dat)
197198
pretty_name = func_name + '(' + ', '.join(printed_args) + ')'
198-
new_obj.extend(['FUNCTION', pretty_name, None]) # the final element will be filled in later
199+
encoded_val = ['FUNCTION', pretty_name, None]
200+
if get_parent:
201+
enclosing_frame_id = get_parent(dat)
202+
encoded_val[2] = enclosing_frame_id
203+
new_obj.extend(encoded_val)
199204
elif typ is types.BuiltinFunctionType:
200205
pretty_name = get_name(dat) + '(...)'
201206
new_obj.extend(['FUNCTION', pretty_name, None])
@@ -247,5 +252,5 @@ def encode_class_or_instance(self, dat, new_obj):
247252
user_attrs = []
248253

249254
for attr in user_attrs:
250-
new_obj.append([self.encode(attr), self.encode(dat.__dict__[attr])])
255+
new_obj.append([self.encode(attr, None), self.encode(dat.__dict__[attr], None)])
251256

v3/pg_logger.py

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,12 @@ def __init__(self, cumulative_mode, finalizer_func):
247247
def get_frame_id(self, cur_frame):
248248
return self.frame_ordered_ids[cur_frame]
249249

250+
# Returns the (lexical) parent of a function value.
251+
def get_parent_of_function(self, val):
252+
if val not in self.closures:
253+
return None
254+
return self.get_frame_id(self.closures[val])
255+
250256

251257
# Returns the (lexical) parent frame of the function that was called
252258
# to create the stack frame 'frame'.
@@ -467,20 +473,7 @@ def create_encoded_stack_entry(cur_frame):
467473
if k == '__module__':
468474
continue
469475

470-
encoded_val = self.encoder.encode(v)
471-
472-
# UGH, this is SUPER ugly but needed for nested function defs
473-
#
474-
# NB: Known limitation -- this will work only for functions
475-
# defined on the top level, not those that are nested within,
476-
# say, tuples or lists
477-
if type(v) in (types.FunctionType, types.MethodType):
478-
try:
479-
enclosing_frame = self.closures[v]
480-
enclosing_frame_id = self.get_frame_id(enclosing_frame)
481-
self.encoder.set_function_parent_frame_ID(encoded_val, enclosing_frame_id)
482-
except KeyError:
483-
pass
476+
encoded_val = self.encoder.encode(v, self.get_parent_of_function)
484477
encoded_locals[k] = encoded_val
485478

486479

@@ -590,20 +583,7 @@ def create_encoded_stack_entry(cur_frame):
590583
# effects of aliasing later down the line ...
591584
encoded_globals = {}
592585
for (k, v) in get_user_globals(tos[0]).items():
593-
encoded_val = self.encoder.encode(v)
594-
595-
# UGH, this is SUPER ugly but needed for nested function defs
596-
#
597-
# NB: Known limitation -- this will work only for functions
598-
# defined on the top level, not those that are nested within,
599-
# say, tuples or lists
600-
if type(v) in (types.FunctionType, types.MethodType):
601-
try:
602-
enclosing_frame = self.closures[v]
603-
enclosing_frame_id = self.get_frame_id(enclosing_frame)
604-
self.encoder.set_function_parent_frame_ID(encoded_val, enclosing_frame_id)
605-
except KeyError:
606-
pass
586+
encoded_val = self.encoder.encode(v, self.get_parent_of_function)
607587
encoded_globals[k] = encoded_val
608588

609589
if k not in self.all_globals_in_order:

v3/tests/backend-tests/john-lambda-lambda.golden

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@
326326
"4": [
327327
"FUNCTION",
328328
"<lambda>(b)",
329-
null
329+
2
330330
]
331331
},
332332
"line": 5,
@@ -462,7 +462,7 @@
462462
"4": [
463463
"FUNCTION",
464464
"<lambda>(b)",
465-
null
465+
2
466466
]
467467
},
468468
"line": 5,

v3/tests/backend-tests/john-lambda-lambda.golden_py3

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@
326326
"4": [
327327
"FUNCTION",
328328
"<lambda>(b)",
329-
null
329+
2
330330
]
331331
},
332332
"line": 5,
@@ -462,7 +462,7 @@
462462
"4": [
463463
"FUNCTION",
464464
"<lambda>(b)",
465-
null
465+
2
466466
]
467467
},
468468
"line": 5,

v3/tests/backend-tests/john-triple-nesting.golden_py3

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@
460460
"5": [
461461
"FUNCTION",
462462
"<lambda>()",
463-
null
463+
2
464464
]
465465
},
466466
"line": 7,
@@ -699,7 +699,7 @@
699699
"7": [
700700
"FUNCTION",
701701
"<lambda>()",
702-
null
702+
1
703703
]
704704
},
705705
"line": 9,

0 commit comments

Comments
 (0)