@study-lenses/trace-py-pyodide
v0.1.0
Published
Python execution tracer for @study-lenses — traces Python code via Pyodide + sys.settrace()
Readme
@study-lenses/trace-py-pyodide
Python execution tracer for
@study-lenses/tracing— traces Python code via Pyodide + sys.settrace()
Pedagogical Purpose
Neutral infrastructure: This package provides raw Python execution traces for educational tool developers. It makes no pedagogical decisions — those belong in the tools that consume it.
The trace data captures function calls and returns with arguments, return values, and call depth. Educational tools decide which subset to show and how to present it.
Who Is This For
Primary — Educational tool developers: Building Study Lenses, custom analysis tools, or other learning environments that need Python execution traces.
Secondary — CS instructors: Using this package directly to build course-specific debugging aids or step-through visualizations.
Install
npm install @study-lenses/trace-py-pyodideQuick Start
import trace from '@study-lenses/trace-py-pyodide';
const code = `
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(5))
`;
const steps = await trace(code);
console.log(steps);
// → [{ step: 1, category: 'call', type: 'FunctionCall', detail: { name: 'fibonacci', args: ['5'], depth: 0 }, ... }, ...]API Summary
@study-lenses/trace-py-pyodide pre-configures all four @study-lenses/tracing wrappers
with the py-pyodide tracer:
| Export | Description |
| ------------------------------ | ------------------------------------------------------- |
| trace(code, config?) | Positional args, throws on error. Default export. |
| tracify | Chainable builder with tracer pre-set, throws on error. |
| embody({ code, config? }) | Keyed args, returns Result (no throw). |
| embodify({ code?, config? }) | Immutable chainable builder, returns Result. |
See DOCS.md for the full API reference.
Design Principles
What this package provides
- Function-level execution traces for Python code (calls and returns)
- Pyodide-based execution (Python in the browser via WebAssembly)
- sys.settrace() instrumentation (automatic, no code modification needed)
- Captures: function name, arguments, return values, call depth, line numbers
- The four standard
@study-lenses/tracingwrappers, pre-bound to this tracer
What this package does NOT do
- Make pedagogical decisions (what to show, how to explain)
- Persist or accumulate traces across calls
- Support languages other than Python
- Trace line-by-line execution (only function calls/returns)
Architecture
Dual-mode execution:
Browser: code → Pyodide (WebAssembly) → sys.settrace() → Step[]
Node.js: code → Python subprocess → sys.settrace() → JSON → Step[]The tracer automatically detects the environment:
- Browser: Uses Pyodide (CPython compiled to WebAssembly) for in-browser execution
- Node.js: Spawns a Python subprocess for testing/CI environments
Both modes use Python's built-in sys.settrace() to capture function call and return
events, which are converted to the @study-lenses/tracing Step[] format.
Step Format
Each step includes:
{
step: number; // 1-indexed
category: 'call' | 'return';
type: 'FunctionCall';
loc: {
start: { line: number; column: number };
end: { line: number; column: number };
};
detail: {
name: string; // Function name
depth: number; // Call stack depth
args?: string[]; // Arguments (for 'call' steps)
returnValue?: string; // Return value (for 'return' steps)
};
}Browser-Only
Important: This package works in both browser and Node.js environments:
- Browser: Uses Pyodide (Python compiled to WebAssembly)
- Node.js: Uses Python subprocess (requires Python 3 installed)
The tracer automatically detects the environment and uses the appropriate method.
For Node.js testing: Ensure Python 3 is installed and available as python3 in your PATH.
Examples
Basic Function Call
import trace from '@study-lenses/trace-py-pyodide';
const steps = await trace(`
def greet(name):
return f"Hello, {name}!"
greet("World")
`);
// Returns 2 steps: call + returnRecursive Function
const steps = await trace(`
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)
factorial(5)
`);
// Returns 10 steps: 5 calls + 5 returnsWith Config Options
import { tracify } from '@study-lenses/trace-py-pyodide';
const steps = await tracify
.code(
`
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
fibonacci(10)
`,
)
.meta({ max: { steps: 50 } }) // Limit to 50 steps
.record();Limitations
- Function-level only: Traces function calls/returns, not line-by-line execution
- Performance (browser): Pyodide initialization takes 3-10 seconds on first load
- Size (browser): Pyodide is ~10MB (cached after first load)
- Node.js requirement: Requires Python 3 installed for Node.js/testing mode
Contributing
See CONTRIBUTING.md and DEV.md.
License
MIT © 2025 Fahed Daibes & Evan Cole
