Skip to content

v0.0.345: sys.settrace / sys.setprofile (F7)#266

Merged
tamnd merged 1 commit into
mainfrom
feat/v0.0.345-settrace-setprofile
Apr 29, 2026
Merged

v0.0.345: sys.settrace / sys.setprofile (F7)#266
tamnd merged 1 commit into
mainfrom
feat/v0.0.345-settrace-setprofile

Conversation

@tamnd

@tamnd tamnd commented Apr 29, 2026

Copy link
Copy Markdown
Owner

Summary

Closes group F7 from the v0.1.0 audit (notes/Spec/1500/1530_goipy_v01_gap_audit.md). Spec at notes/Spec/1500/1539_goipy_v0045_settrace_setprofile.md.

pdb, coverage.py, and third-party profilers (yappi, line_profiler) drive their hooks through sys.settrace/sys.setprofile. Goipy had stub no-ops in threading and pdb and nothing on sys itself; tracers silently never fired.

  • Interp.traceFn / profileFn plus an inTrace re-entry guard so the tracer's own dispatch doesn't recurse.
  • runFrame fires 'call' / 'return' / 'exception' events; the global trace's 'call' return value becomes the per-frame LocalTrace.
  • Frame.LocalTrace and Frame.LastLine; LastLine is seeded to Code.FirstLineNo on frame entry so the RESUME-on-def-line opcode does not fire a stray line event before the first body line — matching CPython 3.11+.
  • Dispatch hot-loop guard: nil LocalTrace is the common path → near-zero overhead. A local trace returning None disables further line events on that frame; a callable replaces the local trace.
  • callFunctionFast frame-pool reset clears LocalTrace + LastLine.
  • Frame f_trace getter/setter wired via LocalTrace.
  • sys.settrace / gettrace / setprofile / getprofile.
  • Fixture 345_settrace_setprofile.pygettrace round-trip, event sequence for f(), per-frame replacement, profile (no line events), disabling mid-execution.

Test plan

  • go test ./... -timeout 600s — green
  • Fixture matches CPython 3.14 byte-for-byte
  • No regression on existing fixtures (especially generator + exception tests)

Out of scope

  • 'opcode' event (f_trace_opcodes stays a no-op).
  • sys.monitoring (PEP 669) — separate audit entry.
  • frame.f_lineno = N jump during pdb.

Closes group F7 from notes/Spec/1500/1530_goipy_v01_gap_audit.md.
Spec at notes/Spec/1500/1539_goipy_v0045_settrace_setprofile.md.

- Interp.traceFn / profileFn / inTrace re-entry guard.
- runFrame fires call/return/exception; result of global trace's
  'call' becomes the per-frame LocalTrace.
- Frame.LocalTrace + LastLine; LastLine seeded to FirstLineNo so
  the RESUME-on-def-line opcode does not fire a stray line event
  before the first body line.
- Dispatch hot-loop guard: nil LocalTrace = near-zero overhead.
  Local trace returning None disables further line events; a
  callable replaces the local trace per CPython.
- callFunctionFast frame-pool reset clears LocalTrace + LastLine.
- Frame f_trace getter/setter wired via LocalTrace.
- sys.settrace / gettrace / setprofile / getprofile.
- Fixture 345_settrace_setprofile.py — round-trip, event sequence
  for f(), per-frame replacement, profile (no line events),
  disable mid-execution.
@tamnd tamnd merged commit 3ef8076 into main Apr 29, 2026
1 check passed
@tamnd tamnd deleted the feat/v0.0.345-settrace-setprofile branch April 29, 2026 07:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant