retracesoftware-proxy 0.2.18__py3-none-any.whl → 0.2.19__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.
- retracesoftware/__main__.py +90 -15
- retracesoftware/autoenable.py +4 -0
- retracesoftware/install/patchfindspec.py +14 -108
- retracesoftware/run.py +4 -6
- {retracesoftware_proxy-0.2.18.dist-info → retracesoftware_proxy-0.2.19.dist-info}/METADATA +1 -1
- {retracesoftware_proxy-0.2.18.dist-info → retracesoftware_proxy-0.2.19.dist-info}/RECORD +8 -16
- retracesoftware/install/install.py +0 -142
- retracesoftware/install/modulepatcher.py +0 -506
- retracesoftware/install/phases.py +0 -338
- retracesoftware/install/predicate.py +0 -92
- retracesoftware/install/record.py +0 -174
- retracesoftware/install/references.py +0 -66
- retracesoftware/install/replay.py +0 -102
- retracesoftware/replay.py +0 -105
- {retracesoftware_proxy-0.2.18.dist-info → retracesoftware_proxy-0.2.19.dist-info}/WHEEL +0 -0
- {retracesoftware_proxy-0.2.18.dist-info → retracesoftware_proxy-0.2.19.dist-info}/top_level.txt +0 -0
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
from retracesoftware.proxy import *
|
|
2
|
-
|
|
3
|
-
from retracesoftware.install import globals
|
|
4
|
-
|
|
5
|
-
import os, json, re, glob
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from datetime import datetime
|
|
8
|
-
from retracesoftware.install.config import env_truthy
|
|
9
|
-
|
|
10
|
-
def recordings(pattern):
|
|
11
|
-
# Turn strftime placeholders into '*' for globbing
|
|
12
|
-
# (very simple replacement: %... -> *)
|
|
13
|
-
glob_pattern = re.sub(r"%[a-zA-Z]", "*", pattern)
|
|
14
|
-
|
|
15
|
-
base_pattern = os.path.basename(pattern)
|
|
16
|
-
|
|
17
|
-
# Find all matching files
|
|
18
|
-
for path in glob.glob(glob_pattern):
|
|
19
|
-
try:
|
|
20
|
-
name = os.path.basename(path)
|
|
21
|
-
datetime.strptime(name, base_pattern)
|
|
22
|
-
yield path
|
|
23
|
-
except:
|
|
24
|
-
pass
|
|
25
|
-
|
|
26
|
-
def latest_from_pattern(pattern: str) -> str | None:
|
|
27
|
-
"""
|
|
28
|
-
Given a strftime-style filename pattern (e.g. "recordings/%Y%m%d_%H%M%S_%f"),
|
|
29
|
-
return the path to the most recent matching file, or None if no files exist.
|
|
30
|
-
"""
|
|
31
|
-
# Derive the datetime format from the pattern (basename only)
|
|
32
|
-
base_pattern = os.path.basename(pattern)
|
|
33
|
-
|
|
34
|
-
def parse_time(path: str):
|
|
35
|
-
name = os.path.basename(path)
|
|
36
|
-
return datetime.strptime(name, base_pattern)
|
|
37
|
-
|
|
38
|
-
# Find the latest by parsed timestamp
|
|
39
|
-
return max(recordings(pattern), key=parse_time)
|
|
40
|
-
|
|
41
|
-
def replay_system(thread_state, immutable_types, config):
|
|
42
|
-
|
|
43
|
-
verbose = env_truthy('RETRACE_VERBOSE', False)
|
|
44
|
-
recording_path = Path(latest_from_pattern(config['recording_path']))
|
|
45
|
-
|
|
46
|
-
# print(f"replay running against path: {recording_path}")
|
|
47
|
-
|
|
48
|
-
globals.recording_path = globals.RecordingPath(recording_path)
|
|
49
|
-
|
|
50
|
-
assert recording_path.exists()
|
|
51
|
-
assert recording_path.is_dir()
|
|
52
|
-
|
|
53
|
-
with open(recording_path / "env", "r", encoding="utf-8") as f:
|
|
54
|
-
os.environ.update(json.load(f))
|
|
55
|
-
|
|
56
|
-
with open(recording_path / "tracing_config.json", "r", encoding="utf-8") as f:
|
|
57
|
-
tracing_config = json.load(f)
|
|
58
|
-
|
|
59
|
-
with open(recording_path / "mainscript", "r", encoding="utf-8") as f:
|
|
60
|
-
mainscript = f.read()
|
|
61
|
-
|
|
62
|
-
call_trace_file = recording_path / "call_trace.txt"
|
|
63
|
-
|
|
64
|
-
if call_trace_file.exists():
|
|
65
|
-
class CallTracer:
|
|
66
|
-
def __init__(self):
|
|
67
|
-
self.file = open(call_trace_file, 'r')
|
|
68
|
-
|
|
69
|
-
def __call__(self, obj):
|
|
70
|
-
recording = json.loads(self.file.readline())
|
|
71
|
-
if obj != recording:
|
|
72
|
-
breakpoint()
|
|
73
|
-
|
|
74
|
-
def close(self):
|
|
75
|
-
self.file.close()
|
|
76
|
-
|
|
77
|
-
# def on_call(self, function_name):
|
|
78
|
-
# recording = self.file.readline()
|
|
79
|
-
# if f'call: {function_name}\n' != recording:
|
|
80
|
-
# breakpoint()
|
|
81
|
-
|
|
82
|
-
# assert f'call: {function_name}\n' == recording
|
|
83
|
-
|
|
84
|
-
# def on_return(self, function_name):
|
|
85
|
-
# recording = self.file.readline()
|
|
86
|
-
# if f'return: {function_name}\n' != recording:
|
|
87
|
-
# breakpoint()
|
|
88
|
-
|
|
89
|
-
# assert f'return: {function_name}\n' == recording
|
|
90
|
-
|
|
91
|
-
call_tracer = CallTracer()
|
|
92
|
-
else:
|
|
93
|
-
call_tracer = None
|
|
94
|
-
|
|
95
|
-
return ReplayProxySystem(thread_state = thread_state,
|
|
96
|
-
immutable_types = immutable_types,
|
|
97
|
-
tracing_config = tracing_config,
|
|
98
|
-
mainscript = mainscript,
|
|
99
|
-
path = recording_path / 'trace.bin',
|
|
100
|
-
tracecalls = env_truthy('RETRACE_ALL', False),
|
|
101
|
-
verbose = verbose,
|
|
102
|
-
magic_markers = env_truthy('RETRACE_MAGIC_MARKERS', False))
|
retracesoftware/replay.py
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import retracesoftware.stream as stream
|
|
2
|
-
from retracesoftware.run import install, run_with_retrace, ImmutableTypes, thread_states
|
|
3
|
-
import argparse
|
|
4
|
-
import sys
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
from retracesoftware.proxy.thread import thread_id
|
|
7
|
-
from retracesoftware.proxy.replay import ReplayProxySystem
|
|
8
|
-
import retracesoftware.utils as utils
|
|
9
|
-
import json
|
|
10
|
-
from retracesoftware.stackdifference import on_stack_difference
|
|
11
|
-
from retracesoftware.exceptions import RecordingNotFoundError
|
|
12
|
-
|
|
13
|
-
def parse_args():
|
|
14
|
-
parser = argparse.ArgumentParser(
|
|
15
|
-
prog=f"python -m {sys.argv[0]}",
|
|
16
|
-
description="Run a Python module with debugging, logging, etc."
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
parser.add_argument(
|
|
20
|
-
'--verbose',
|
|
21
|
-
action='store_true',
|
|
22
|
-
help='Enable verbose output'
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
parser.add_argument(
|
|
26
|
-
'--timeout', # or '-r'
|
|
27
|
-
type = int, # ensures it's a string (optional, but safe)
|
|
28
|
-
default = 60, # default value if not provided
|
|
29
|
-
help = 'the directory to place the recording files'
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
parser.add_argument(
|
|
33
|
-
'--recording', # or '-r'
|
|
34
|
-
type = str, # ensures it's a string (optional, but safe)
|
|
35
|
-
default = '.', # default value if not provided
|
|
36
|
-
help = 'the directory to place the recording files'
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
return parser.parse_args()
|
|
40
|
-
|
|
41
|
-
def load_json(file):
|
|
42
|
-
with open(file, "r", encoding="utf-8") as f:
|
|
43
|
-
return json.load(f)
|
|
44
|
-
|
|
45
|
-
def main():
|
|
46
|
-
# import debugpy
|
|
47
|
-
|
|
48
|
-
# port = 1977
|
|
49
|
-
# debugpy.listen(("127.0.0.1", port))
|
|
50
|
-
# debugpy.wait_for_client()
|
|
51
|
-
|
|
52
|
-
# self.reader = stream.reader(path,
|
|
53
|
-
# thread = thread_id,
|
|
54
|
-
# timeout_seconds = 60,
|
|
55
|
-
# verbose = verbose,
|
|
56
|
-
# on_stack_difference = thread_state.wrap('disabled', on_stack_difference),
|
|
57
|
-
# magic_markers = magic_markers)
|
|
58
|
-
|
|
59
|
-
# return ReplayProxySystem(thread_state = thread_state,
|
|
60
|
-
# immutable_types = immutable_types,
|
|
61
|
-
# tracing_config = tracing_config,
|
|
62
|
-
# mainscript = mainscript,
|
|
63
|
-
# path = recording_path / 'trace.bin',
|
|
64
|
-
# tracecalls = env_truthy('RETRACE_ALL', False),
|
|
65
|
-
# verbose = verbose,
|
|
66
|
-
# magic_markers = env_truthy('RETRACE_MAGIC_MARKERS', False))
|
|
67
|
-
|
|
68
|
-
args = parse_args()
|
|
69
|
-
path = Path(args.recording)
|
|
70
|
-
|
|
71
|
-
if not path.exists():
|
|
72
|
-
raise RecordingNotFoundError(f"Recording path: {path} does not exist")
|
|
73
|
-
|
|
74
|
-
settings = load_json(path / "settings.json")
|
|
75
|
-
|
|
76
|
-
thread_state = utils.ThreadState(*thread_states)
|
|
77
|
-
|
|
78
|
-
with stream.reader(path = path / 'trace.bin',
|
|
79
|
-
thread = thread_id,
|
|
80
|
-
timeout_seconds = args.timeout,
|
|
81
|
-
verbose = args.verbose,
|
|
82
|
-
on_stack_difference = thread_state.wrap('disabled', on_stack_difference),
|
|
83
|
-
magic_markers = settings['magic_markers']) as reader:
|
|
84
|
-
|
|
85
|
-
tracing_config = {}
|
|
86
|
-
|
|
87
|
-
system = ReplayProxySystem(
|
|
88
|
-
reader = reader,
|
|
89
|
-
thread_state = thread_state,
|
|
90
|
-
immutable_types = ImmutableTypes(),
|
|
91
|
-
tracing_config = tracing_config,
|
|
92
|
-
tracecalls = settings['trace_inputs'])
|
|
93
|
-
|
|
94
|
-
install(system)
|
|
95
|
-
|
|
96
|
-
run_with_retrace(system, settings['argv'])
|
|
97
|
-
|
|
98
|
-
# install(system)
|
|
99
|
-
|
|
100
|
-
# run_with_retrace(system, args.rest[1:])
|
|
101
|
-
|
|
102
|
-
# runpy.run_module('foo', run_name="__main__", alter_sys=False)
|
|
103
|
-
|
|
104
|
-
if __name__ == "__main__":
|
|
105
|
-
main()
|
|
File without changes
|
{retracesoftware_proxy-0.2.18.dist-info → retracesoftware_proxy-0.2.19.dist-info}/top_level.txt
RENAMED
|
File without changes
|