Thanks Louie.
I've adjusted the issue title, as I think the core RFE is that we'd like the following helper function to work exactly the same way as calling sys.setprofile directly:
def setprofile_helper(f):
sys.setprofile(f)
The following utility function can be used to demonstrate the current discrepancy:
def profile_call(setprofile, call):
pr = profile.Profile()
setprofile(pr.dispatcher)
try:
call()
finally:
setprofile(None)
return pr
Specifically:
```
>>> profile_call(sys.setprofile, lambda:print("Profiled!"))
Profiled!
<profile.Profile object at 0x7fb2265966d8>
>>> profile_call(setprofile_helper, lambda:print("Profiled!"))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in profile_call
File "<stdin>", line 2, in setprofile_helper
File "/usr/lib64/python3.5/profile.py", line 209, in trace_dispatch_i
if self.dispatch[event](self, frame, t):
File "/usr/lib64/python3.5/profile.py", line 293, in trace_dispatch_return
assert frame is self.cur[-2].f_back, ("Bad return", self.cur[-3])
AssertionError: ('Bad return', ('profile', 0, 'profiler'))
```
If we can figure out a way to do it reliably, the most desirable approach would be to make helper functions like the above "just work", perhaps by remembering the stack frame where the profiler was *defined*, and using that as the reference point to construct the synthetic stack the first time a trace dispatch occurs.
If that transparent-to-the-user approach doesn't appear to be feasible, an alternative would be to offer a new private method on Profile objects to adjust their synthetic stack by one level, as if `sys.setprofile` had been called *before* the call into the helper function.
That is, a profiler-aware alternative to the helper function above might look like:
def profile_helper(pr):
sys.setprofile(pr.dispatcher)
pr._adjust_stack()
and that's then the approach that the `__enter__` method would use to implement context management support.
The advantage of the latter private option is that it wouldn't need to support arbitrary helper functions, just the specific implementation of `__enter__` for issue 9285.
In either case, I *don't* think changing the assertion is the right answer - instead, I think the internal profiler state needs to be adjusted so the assertion passes without modification.
|