This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author ncoghlan
Recipients louielu, ncoghlan
Date 2017-04-22.05:55:19
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1492840520.03.0.457307563831.issue30113@psf.upfronthosting.co.za>
In-reply-to
Content
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.
History
Date User Action Args
2017-04-22 05:55:20ncoghlansetrecipients: + ncoghlan, louielu
2017-04-22 05:55:20ncoghlansetmessageid: <1492840520.03.0.457307563831.issue30113@psf.upfronthosting.co.za>
2017-04-22 05:55:20ncoghlanlinkissue30113 messages
2017-04-22 05:55:19ncoghlancreate