atrace 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
atrace/__init__.py CHANGED
@@ -1,2 +1,97 @@
1
- def hello() -> str:
2
- return "Hello from atrace!"
1
+ import copy
2
+ import inspect
3
+ import sys
4
+ from types import FrameType
5
+ from typing import Any
6
+
7
+ module_of_interest = None
8
+ last_locals = {}
9
+
10
+
11
+ def ignore_variable(name: str, value: Any):
12
+ # if name.startswith("_"):
13
+ # return True
14
+ return callable(value) # Functions, modules, tout ça
15
+
16
+
17
+ def copy_carefully_using_ignored_variables(d: dict[str, Any]):
18
+ res = {}
19
+ for k, v in d.items():
20
+ if not ignore_variable(k, v):
21
+ res[k] = copy.deepcopy(v)
22
+ return res
23
+
24
+
25
+ def copy_carefully(d: dict[str, Any]):
26
+ res = {}
27
+ for k, v in d.items():
28
+ try:
29
+ v_copy = copy.deepcopy(v)
30
+ except:
31
+ v_copy = v
32
+ res[k] = v_copy
33
+ return res
34
+
35
+
36
+ def trace_vars(frame: FrameType, event: str, arg: Any):
37
+ if inspect.getmodule(frame) != module_of_interest:
38
+ return
39
+ if event != "line":
40
+ return trace_vars
41
+ code = frame.f_code
42
+ lineno = frame.f_lineno
43
+ locals_now = copy_carefully(frame.f_locals)
44
+ global last_locals
45
+
46
+ if last_locals is None: # We're being unloaded, it's the end of the program
47
+ return None
48
+
49
+ if code.co_name not in last_locals:
50
+ last_locals[code.co_name] = locals_now
51
+ return trace_vars
52
+
53
+ old_locals = last_locals[code.co_name]
54
+
55
+ for var, new_val in locals_now.items():
56
+ if not ignore_variable(var, new_val):
57
+ if var not in old_locals:
58
+ print(f"[{lineno}] NEW {var} = {new_val}")
59
+ elif old_locals[var] != new_val:
60
+ print(f"[{lineno}] MODIFIED {var}: {old_locals[var]} → {new_val}")
61
+
62
+ for var, old_val in old_locals.items():
63
+ if var not in locals_now:
64
+ if not ignore_variable(var, old_val):
65
+ print(f"[{lineno}] DELETED {var}")
66
+
67
+ last_locals[code.co_name] = locals_now
68
+ return trace_vars
69
+
70
+
71
+ def just_kicking_off(frame: FrameType, event: str, arg: Any):
72
+ return None
73
+
74
+
75
+ def get_importer_frame():
76
+ # Get the current call stack
77
+ for frame_info in inspect.stack():
78
+ # Filter out internal importlib frames and the current module's frame
79
+ filename = frame_info.filename
80
+ if not filename.startswith("<") and filename != __file__:
81
+ return frame_info.frame
82
+ return None
83
+
84
+
85
+ # It also kicks off the tracing machinery (so that the lines below work)
86
+ sys.settrace(just_kicking_off)
87
+
88
+
89
+ # This reaches into the importing module's frame to setup tracing of code outside of functions
90
+ importer_frame = get_importer_frame()
91
+ if importer_frame:
92
+ importer_frame.f_trace = trace_vars
93
+ module_of_interest = inspect.getmodule(importer_frame)
94
+ # This will work next time we enter a function.
95
+ sys.settrace(trace_vars)
96
+ else:
97
+ print("Cannot trace")
@@ -0,0 +1,75 @@
1
+ Metadata-Version: 2.4
2
+ Name: atrace
3
+ Version: 0.1.2
4
+ Summary: Generate trace tables for programs
5
+ Project-URL: Repository, https://github.com/nwolff/atrace.git
6
+ Author-email: Nicholas Wolff <nwolff@gmail.com>
7
+ Requires-Python: >=3.7
8
+ Description-Content-Type: text/markdown
9
+
10
+ # TODO:
11
+
12
+ - ignore function definitions (look at the type of object)
13
+
14
+ - display at end only
15
+
16
+ - entering a function, binding the local arguments, returning
17
+
18
+ # Usage
19
+
20
+ Automatically prints a trace table of a program once the execution is finished.
21
+
22
+ Just import the module.
23
+
24
+ An animated example of a trace table: https://www.101computing.net/using-trace-tables/
25
+
26
+ # Requirements
27
+
28
+ - Should not interfere with the running program (apart from capturing stdout)
29
+ - Should display the trace at the end of execution (not while the program is interacting with the user)
30
+ - Should display the trace even if an exception interrupts the program
31
+ - Should display the trace even if the user interrupts the program
32
+ - Should handle mutations to objects like lists
33
+ - Should handle functions properly:
34
+ - entering the function
35
+ - binding the local arguments
36
+ - returning
37
+
38
+ # Supported environments
39
+
40
+ - Thonny, which adds a shitload of magic
41
+ - python 3.10+
42
+
43
+ # Not in scope
44
+
45
+ - Multithreaded programs
46
+
47
+ # Implementation
48
+
49
+ To trace variables :
50
+
51
+ - Either https://docs.python.org/3/library/sys.html#sys.settrace
52
+ - Or https://docs.python.org/3/library/trace.html
53
+
54
+ To capture stdout :
55
+
56
+ - Either https://docs.python.org/3/library/contextlib.html#contextlib.redirect_stdout
57
+ - Or just reassign stdout
58
+
59
+ To trap sigint:
60
+
61
+ - https://stackoverflow.com/questions/1112343/how-do-i-capture-sigint-in-python
62
+
63
+ # Build
64
+
65
+ Automatically deployed to pypi every time a new tag is pushed: https://pypi.org/project/atrace/
66
+
67
+ # Technical Refs
68
+
69
+ - First similar thing I found, doesn't work (chokes on deep copying some variables): https://github.com/DarshanLakshman/PyTracerTool
70
+
71
+ - 11 years old, doesn't work: https://github.com/mihneadb/python-execution-trace
72
+
73
+ - A hot mess: https://stackoverflow.com/questions/1645028/trace-table-for-python-programs
74
+
75
+ - A tutorial on the trace module: https://pymotw.com/2/trace/
@@ -0,0 +1,5 @@
1
+ atrace/__init__.py,sha256=D-RmBnWrMXqyEb1EyAaJw4SIPIma2ce74iBCShrcIm4,2708
2
+ atrace/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ atrace-0.1.2.dist-info/METADATA,sha256=VP1L_GRfVJ3vdlgk9te_dbHXyoTBRFQY_-Qap5Z-iUU,2128
4
+ atrace-0.1.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
5
+ atrace-0.1.2.dist-info/RECORD,,
@@ -1,5 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: atrace
3
- Version: 0.1.0
4
- Author-email: Nicholas Wolff <nwolff@gmail.com>
5
- Requires-Python: >=3.7
@@ -1,5 +0,0 @@
1
- atrace/__init__.py,sha256=aT0BUPvWpbdoOpN9gOZcLNFxgENSl-ptao0487nheGE,52
2
- atrace/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- atrace-0.1.0.dist-info/METADATA,sha256=P1Ej3l3jeT-SKZnSNzwb-zH7q9cwCW_7mf6DiIrWM0I,121
4
- atrace-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
5
- atrace-0.1.0.dist-info/RECORD,,
File without changes