Skip to content

Commit 9a8a256

Browse files
committed
Run the recorder as a script python -m codetracer_python_recorder [args] script.py [script args]
codetracer-python-recorder/codetracer_python_recorder/__init__.py: codetracer-python-recorder/codetracer_python_recorder/__main__.py: hello.py: trace.json: trace.metadata.json: trace.paths.json: Signed-off-by: Tzanko Matev <[email protected]>
1 parent ddf3653 commit 9a8a256

File tree

2 files changed

+93
-3
lines changed

2 files changed

+93
-3
lines changed

codetracer-python-recorder/codetracer_python_recorder/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
maintains placeholder state and performs no actual tracing.
88
"""
99

10-
from .api import *
11-
12-
__all__ = api.__all__
10+
from . import api as _api
11+
from .api import * # re-export public API symbols
1312

13+
__all__ = _api.__all__
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
"""CLI to record a trace while running a Python script.
2+
3+
Usage:
4+
python -m codetracer_python_recorder [codetracer options] <script.py> [script args...]
5+
6+
Codetracer options (must appear before the script path):
7+
--codetracer-trace PATH Output events file (default: trace.bin or trace.json)
8+
--codetracer-format {binary,json} Output format (default: binary)
9+
--codetracer-capture-values BOOL Whether to capture values (default: true)
10+
11+
Examples:
12+
python -m codetracer_python_recorder --codetracer-format=json app.py --flag=1
13+
python -m codetracer_python_recorder --codetracer-trace=out.bin script.py --x=2
14+
python -m codetracer_python_recorder --codetracer-capture-values=false script.py
15+
"""
16+
from __future__ import annotations
17+
18+
import runpy
19+
import sys
20+
from pathlib import Path
21+
22+
from . import DEFAULT_FORMAT, start, stop
23+
import argparse
24+
25+
26+
def _default_trace_path(fmt: str) -> Path:
27+
# Keep a simple filename; Rust side derives sidecars (metadata/paths)
28+
if fmt == "json":
29+
return Path.cwd() / "trace.json"
30+
return Path.cwd() / "trace.bin"
31+
32+
33+
def main(argv: list[str] | None = None) -> int:
34+
if argv is None:
35+
argv = sys.argv[1:]
36+
37+
parser = argparse.ArgumentParser(add_help=True)
38+
parser.add_argument(
39+
"--codetracer-trace",
40+
dest="trace",
41+
default=None,
42+
help="Path to trace folder. If omitted, defaults to trace.bin or trace.json in the current directory based on --codetracer-format.",
43+
)
44+
parser.add_argument(
45+
"--codetracer-format",
46+
dest="format",
47+
choices=["binary", "json"],
48+
default=DEFAULT_FORMAT,
49+
help="Output format for trace events. 'binary' is compact; 'json' is human-readable. Default: %(default)s.",
50+
)
51+
# Only parse our options; leave script and script args in unknown
52+
ns, unknown = parser.parse_known_args(argv)
53+
54+
# Validate that the first unknown token is a script path; otherwise show usage.
55+
if not unknown or not Path(unknown[0]).exists():
56+
sys.stderr.write("Usage: python -m codetracer_python_recorder [codetracer options] <script.py> [args...]\n")
57+
return 2
58+
59+
script_path = Path(unknown[0])
60+
script_args = unknown[1:]
61+
62+
fmt = ns.format or DEFAULT_FORMAT
63+
trace_path = Path(ns.trace) if ns.trace else _default_trace_path(fmt)
64+
65+
old_argv = sys.argv
66+
sys.argv = [str(script_path)] + script_args
67+
# Activate tracing only after entering the target script file.
68+
session = start(
69+
trace_path,
70+
format=fmt,
71+
start_on_enter=script_path,
72+
)
73+
try:
74+
runpy.run_path(str(script_path.resolve()), run_name="__main__")
75+
return 0
76+
except SystemExit as e:
77+
# Preserve script's exit code
78+
code = e.code if isinstance(e.code, int) else 1
79+
return code
80+
finally:
81+
# Ensure tracer stops and files are flushed
82+
try:
83+
session.flush()
84+
finally:
85+
stop()
86+
sys.argv = old_argv
87+
88+
89+
if __name__ == "__main__": # pragma: no cover
90+
raise SystemExit(main())

0 commit comments

Comments
 (0)