|
1 | | -import ast, builtins, dis, inspect, os, sys, textwrap |
| 1 | +import ast, builtins, dis, inspect, os, sys, sysconfig, textwrap |
2 | 2 | from fastcore.utils import * |
3 | 3 |
|
4 | 4 | comp_node_types = (ast.ListComp, ast.SetComp, ast.DictComp, ast.GeneratorExp) |
@@ -86,6 +86,27 @@ def tracefunc(fn, /, *args, target_func=None, **kwargs): |
86 | 86 |
|
87 | 87 | stack_anchor = fn.__code__ if target_func is not None else None |
88 | 88 | stack_base = os.path.dirname(stack_anchor.co_filename) if stack_anchor else None |
| 89 | + repls = [] |
| 90 | + venv = os.environ.get("VIRTUAL_ENV") |
| 91 | + if venv: repls.append((os.path.realpath(venv), "$VIRTUAL_ENV")) |
| 92 | + home = os.path.expanduser("~") |
| 93 | + if home: repls.append((os.path.realpath(home), "~")) |
| 94 | + for p, label in ( |
| 95 | + (sys.prefix, "$PYTHON_PREFIX"), |
| 96 | + (getattr(sys, "base_prefix", None), "$PYTHON_BASE"), |
| 97 | + (getattr(sys, "exec_prefix", None), "$PYTHON_EXEC_PREFIX"), |
| 98 | + (getattr(sys, "base_exec_prefix", None), "$PYTHON_BASE_EXEC_PREFIX"), |
| 99 | + ): |
| 100 | + if p: repls.append((os.path.realpath(p), label)) |
| 101 | + paths = sysconfig.get_paths() |
| 102 | + for key, label in ( |
| 103 | + ("purelib", "$SITE_PACKAGES"), |
| 104 | + ("platlib", "$PLAT_SITE_PACKAGES"), |
| 105 | + ("stdlib", "$PYTHON_STDLIB"), |
| 106 | + ("platstdlib", "$PYTHON_PLAT_STDLIB"), |
| 107 | + ): |
| 108 | + if key in paths: repls.append((os.path.realpath(paths[key]), label)) |
| 109 | + repls.sort(key=lambda x: len(x[0]), reverse=True) |
89 | 110 | if target_func is None: target_func = fn |
90 | 111 |
|
91 | 112 | try: src_lines, block_first_lineno = inspect.getsourcelines(target_func) |
@@ -284,12 +305,19 @@ def _stack_str(frame): |
284 | 305 | frames = frames[i:] |
285 | 306 | break |
286 | 307 | else: return "" |
| 308 | + def _shorten(path): |
| 309 | + if stack_base and path.startswith(stack_base + os.sep): |
| 310 | + return os.path.relpath(path, stack_base) |
| 311 | + if not os.path.isabs(path): return path |
| 312 | + for base, label in repls: |
| 313 | + if path == base or path.startswith(base + os.sep): |
| 314 | + return label + path[len(base):] |
| 315 | + return path |
287 | 316 | out = [] |
288 | 317 | for fr in frames: |
289 | | - path = fr.f_code.co_filename |
290 | | - if stack_base and path.startswith(stack_base + os.sep): |
291 | | - path = os.path.relpath(path, stack_base) |
292 | | - out.append(f"{fr.f_code.co_name} ({path}:{fr.f_lineno})") |
| 318 | + path = _shorten(fr.f_code.co_filename) |
| 319 | + name = getattr(fr.f_code, "co_qualname", fr.f_code.co_name) |
| 320 | + out.append(f"{name} ({path}:{fr.f_lineno})") |
293 | 321 | return "\n".join(out) |
294 | 322 |
|
295 | 323 | def _snapshot(call_idx, line_id, frame, *, force=False): |
|
0 commit comments