retracesoftware-proxy 0.1.13__py3-none-any.whl → 0.1.14__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/config.json +19 -7
- retracesoftware/install/patcher.py +56 -10
- retracesoftware/install/record.py +9 -3
- retracesoftware/proxy/__init__.py +1 -1
- retracesoftware/proxy/globalref.py +31 -0
- retracesoftware/proxy/proxytype.py +10 -4
- retracesoftware/proxy/record.py +37 -19
- retracesoftware/proxy/replay.py +30 -9
- retracesoftware/proxy/thread.py +16 -4
- {retracesoftware_proxy-0.1.13.dist-info → retracesoftware_proxy-0.1.14.dist-info}/METADATA +1 -1
- {retracesoftware_proxy-0.1.13.dist-info → retracesoftware_proxy-0.1.14.dist-info}/RECORD +13 -12
- {retracesoftware_proxy-0.1.13.dist-info → retracesoftware_proxy-0.1.14.dist-info}/WHEEL +0 -0
- {retracesoftware_proxy-0.1.13.dist-info → retracesoftware_proxy-0.1.14.dist-info}/top_level.txt +0 -0
retracesoftware/config.json
CHANGED
|
@@ -159,8 +159,10 @@
|
|
|
159
159
|
"modules": {
|
|
160
160
|
"_imp": {
|
|
161
161
|
"patch_extension_exec": ["exec_dynamic", "exec_builtin"],
|
|
162
|
-
"
|
|
163
|
-
"
|
|
162
|
+
"comment": {
|
|
163
|
+
"with_state": {
|
|
164
|
+
"internal": ["create_dynamic"]
|
|
165
|
+
}
|
|
164
166
|
}
|
|
165
167
|
},
|
|
166
168
|
"bdb": {
|
|
@@ -186,7 +188,11 @@
|
|
|
186
188
|
|
|
187
189
|
"importlib._bootstrap": {
|
|
188
190
|
"with_state": {
|
|
189
|
-
"bootstrap": [
|
|
191
|
+
"bootstrap": [
|
|
192
|
+
"_load_unlocked",
|
|
193
|
+
"_find_spec",
|
|
194
|
+
"_lock_unlock_module",
|
|
195
|
+
"_get_module_lock"]
|
|
190
196
|
}
|
|
191
197
|
},
|
|
192
198
|
|
|
@@ -218,14 +224,20 @@
|
|
|
218
224
|
]
|
|
219
225
|
},
|
|
220
226
|
"types": {
|
|
227
|
+
"patch_hash": ["FunctionType"],
|
|
221
228
|
"immutable_types": [
|
|
222
|
-
"TracebackType"
|
|
229
|
+
"TracebackType",
|
|
230
|
+
"ModuleType"
|
|
223
231
|
]
|
|
224
232
|
},
|
|
225
233
|
"builtins": {
|
|
226
|
-
"
|
|
227
|
-
|
|
228
|
-
|
|
234
|
+
"patch_hash": ["object"],
|
|
235
|
+
|
|
236
|
+
"comment": {
|
|
237
|
+
"replace": {
|
|
238
|
+
"set": "retracesoftware_utils.set",
|
|
239
|
+
"frozenset": "retracesoftware_utils.frozenset"
|
|
240
|
+
}
|
|
229
241
|
},
|
|
230
242
|
"immutable_types": [
|
|
231
243
|
"BaseException",
|
|
@@ -121,9 +121,22 @@ def patch(func):
|
|
|
121
121
|
if isinstance(spec, str):
|
|
122
122
|
return wrapper(self, [spec], mod_dict)
|
|
123
123
|
elif isinstance(spec, list):
|
|
124
|
-
|
|
124
|
+
res = {}
|
|
125
|
+
for name in spec:
|
|
126
|
+
if name in mod_dict:
|
|
127
|
+
value = func(self, mod_dict[name])
|
|
128
|
+
if value is not None:
|
|
129
|
+
res[name] = value
|
|
130
|
+
return res
|
|
125
131
|
elif isinstance(spec, dict):
|
|
126
|
-
return {name: func(self, mod_dict[name], value) for name, value in spec.items() if name in mod_dict}
|
|
132
|
+
# return {name: func(self, mod_dict[name], value) for name, value in spec.items() if name in mod_dict}
|
|
133
|
+
res = {}
|
|
134
|
+
for name,value in spec.items():
|
|
135
|
+
if name in mod_dict:
|
|
136
|
+
value = func(self, mod_dict[name], value)
|
|
137
|
+
if value is not None:
|
|
138
|
+
res[name] = value
|
|
139
|
+
return res
|
|
127
140
|
else:
|
|
128
141
|
raise Exception('TODO')
|
|
129
142
|
|
|
@@ -155,6 +168,11 @@ def wrap_method_descriptors(wrapper, prefix, base):
|
|
|
155
168
|
|
|
156
169
|
return extended
|
|
157
170
|
|
|
171
|
+
class PerThread(threading.local):
|
|
172
|
+
def __init__(self):
|
|
173
|
+
self.internal = utils.counter()
|
|
174
|
+
self.externak = utils.counter()
|
|
175
|
+
|
|
158
176
|
class Patcher:
|
|
159
177
|
|
|
160
178
|
def __init__(self, thread_state, config, system,
|
|
@@ -164,7 +182,7 @@ class Patcher:
|
|
|
164
182
|
post_commit = None):
|
|
165
183
|
|
|
166
184
|
# validate(config)
|
|
167
|
-
|
|
185
|
+
system.set_thread_id(0)
|
|
168
186
|
# utils.set_thread_id(0)
|
|
169
187
|
self.thread_counter = system.sync(utils.counter(1))
|
|
170
188
|
# self.set_thread_number = set_thread_number
|
|
@@ -181,6 +199,13 @@ class Patcher:
|
|
|
181
199
|
self.exclude_paths = [re.compile(s) for s in config.get('exclude_paths', [])]
|
|
182
200
|
self.typepatcher = {}
|
|
183
201
|
|
|
202
|
+
per_thread = PerThread()
|
|
203
|
+
|
|
204
|
+
self.hashfunc = self.thread_state.dispatch(
|
|
205
|
+
functional.constantly(None),
|
|
206
|
+
internal = functional.repeatedly(functional.partial(getattr, per_thread, 'internal')),
|
|
207
|
+
external = functional.repeatedly(functional.partial(getattr, per_thread, 'external')))
|
|
208
|
+
|
|
184
209
|
def is_phase(name): return getattr(getattr(self, name, None), "is_phase", False)
|
|
185
210
|
|
|
186
211
|
self.phases = [(name, getattr(self, name)) for name in Patcher.__dict__.keys() if is_phase(name)]
|
|
@@ -303,19 +328,35 @@ class Patcher:
|
|
|
303
328
|
source.co_name == '<module>' and inspect.getmodule(source)
|
|
304
329
|
|
|
305
330
|
def exec_wrapper(source, *args,**kwargs):
|
|
306
|
-
|
|
307
|
-
|
|
331
|
+
module = None
|
|
332
|
+
|
|
333
|
+
with self.thread_state.select('disabled'):
|
|
334
|
+
if is_module_exec(source):
|
|
308
335
|
module = inspect.getmodule(source)
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
336
|
+
|
|
337
|
+
if module:
|
|
338
|
+
result = exec(source, *args, **kwargs)
|
|
312
339
|
self(module)
|
|
313
|
-
|
|
314
340
|
return result
|
|
315
341
|
else:
|
|
316
342
|
return exec(source, *args,**kwargs)
|
|
317
343
|
|
|
318
|
-
|
|
344
|
+
# if self.thread_state.value != 'bootstrap':
|
|
345
|
+
|
|
346
|
+
# and is_module_exec(source):
|
|
347
|
+
# with self.thread_state.select('disabled'):
|
|
348
|
+
# module = inspect.getmodule(source)
|
|
349
|
+
# with self.thread_state.select('internal'):
|
|
350
|
+
# result = exec(source, *args, **kwargs)
|
|
351
|
+
|
|
352
|
+
# self(module)
|
|
353
|
+
|
|
354
|
+
# return result
|
|
355
|
+
# else:
|
|
356
|
+
# return exec(source, *args,**kwargs)
|
|
357
|
+
|
|
358
|
+
return self.thread_state.dispatch(exec, internal = exec_wrapper)
|
|
359
|
+
# self.thread_state.wrap(desired_state = 'disabled', function = exec_wrapper)
|
|
319
360
|
|
|
320
361
|
@patch
|
|
321
362
|
def sync_types(self, value):
|
|
@@ -372,6 +413,11 @@ class Patcher:
|
|
|
372
413
|
|
|
373
414
|
return updates
|
|
374
415
|
|
|
416
|
+
@patch
|
|
417
|
+
def patch_hash(self, cls):
|
|
418
|
+
print(f'patching hash for: {cls}')
|
|
419
|
+
utils.patch_hash(cls = cls, hashfunc = self.hashfunc)
|
|
420
|
+
|
|
375
421
|
@patch
|
|
376
422
|
def patch_extension_exec(self, exec):
|
|
377
423
|
|
|
@@ -13,9 +13,15 @@ from datetime import datetime
|
|
|
13
13
|
import json
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
|
-
class ThreadSwitch:
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
# class ThreadSwitch:
|
|
17
|
+
# def __init__(self, id):
|
|
18
|
+
# self.id = id
|
|
19
|
+
|
|
20
|
+
# def __repr__(self):
|
|
21
|
+
# return f'ThreadSwitch<{self.id}>'
|
|
22
|
+
|
|
23
|
+
# def __str__(self):
|
|
24
|
+
# return f'ThreadSwitch<{self.id}>'
|
|
19
25
|
|
|
20
26
|
def write_files(recording_path):
|
|
21
27
|
with open(recording_path / 'env', 'w') as f:
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import types
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
def find_module_name(mod):
|
|
5
|
+
for name,value in sys.modules.items():
|
|
6
|
+
if value is mod:
|
|
7
|
+
return name
|
|
8
|
+
|
|
9
|
+
raise Exception(f"Cannot create GlobalRef as module {mod} not found in sys.modules")
|
|
10
|
+
|
|
11
|
+
class GlobalRef:
|
|
12
|
+
__slots__ = ['parts']
|
|
13
|
+
|
|
14
|
+
def __init__(self, obj):
|
|
15
|
+
if isinstance(obj, types.ModuleType):
|
|
16
|
+
self.parts = (find_module_name(obj),)
|
|
17
|
+
else:
|
|
18
|
+
raise Exception(f"Cannot create GlobalRef from {obj}")
|
|
19
|
+
|
|
20
|
+
def __call__(self):
|
|
21
|
+
module = self.parts[0]
|
|
22
|
+
|
|
23
|
+
if len(self.parts) == 0:
|
|
24
|
+
return module
|
|
25
|
+
else:
|
|
26
|
+
obj = getattr(module, self.parts[1])
|
|
27
|
+
|
|
28
|
+
if len(self.parts) == 1:
|
|
29
|
+
return obj
|
|
30
|
+
else:
|
|
31
|
+
raise Exception(f"TODO")
|
|
@@ -214,10 +214,16 @@ def dynamic_proxytype(handler, cls):
|
|
|
214
214
|
|
|
215
215
|
for name in superdict(cls).keys():
|
|
216
216
|
if name not in blacklist:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if
|
|
220
|
-
|
|
217
|
+
try:
|
|
218
|
+
value = getattr(cls, name)
|
|
219
|
+
if is_descriptor(value):
|
|
220
|
+
if utils.is_method_descriptor(value):
|
|
221
|
+
spec[name] = wrap(value)
|
|
222
|
+
except Exception as error:
|
|
223
|
+
print(f'FOO! {cls} {name} {error}')
|
|
224
|
+
breakpoint()
|
|
225
|
+
raise
|
|
226
|
+
|
|
221
227
|
# else:
|
|
222
228
|
# spec[name] = DescriptorProxy(handler = handler, target = value)
|
|
223
229
|
|
retracesoftware/proxy/record.py
CHANGED
|
@@ -5,9 +5,10 @@ import retracesoftware.stream as stream
|
|
|
5
5
|
from retracesoftware.proxy.proxytype import *
|
|
6
6
|
# from retracesoftware.proxy.gateway import gateway_pair
|
|
7
7
|
from retracesoftware.proxy.proxysystem import ProxySystem
|
|
8
|
-
from retracesoftware.proxy.thread import write_thread_switch
|
|
8
|
+
from retracesoftware.proxy.thread import write_thread_switch, ThreadSwitch
|
|
9
9
|
from retracesoftware.install.tracer import Tracer
|
|
10
10
|
from retracesoftware.proxy.stubfactory import StubRef, ExtendedRef
|
|
11
|
+
from retracesoftware.proxy.globalref import GlobalRef
|
|
11
12
|
|
|
12
13
|
import sys
|
|
13
14
|
import os
|
|
@@ -69,14 +70,11 @@ class RecordProxySystem(ProxySystem):
|
|
|
69
70
|
super().after_fork_in_parent()
|
|
70
71
|
self.thread_state.value = self.saved_thread_state
|
|
71
72
|
self.writer.reopen()
|
|
72
|
-
|
|
73
|
-
def sync(self, function):
|
|
74
|
-
write_sync = functional.always(self.writer.handle('SYNC'))
|
|
75
|
-
|
|
76
|
-
return utils.observer(
|
|
77
|
-
on_call = functional.firstof(self.thread_switch_monitor, write_sync),
|
|
78
|
-
function = function)
|
|
79
73
|
|
|
74
|
+
def set_thread_id(self, id):
|
|
75
|
+
utils.set_thread_id(self.writer.handle(ThreadSwitch(id)))
|
|
76
|
+
# utils.set_thread_id(id)
|
|
77
|
+
|
|
80
78
|
def __init__(self, thread_state,
|
|
81
79
|
immutable_types,
|
|
82
80
|
tracing_config,
|
|
@@ -91,6 +89,15 @@ class RecordProxySystem(ProxySystem):
|
|
|
91
89
|
|
|
92
90
|
self.writer = stream.writer(path)
|
|
93
91
|
|
|
92
|
+
def on_switch():
|
|
93
|
+
print(f"On thread switch!!!")
|
|
94
|
+
# print(f"On thread switch!!!: {utils.thread_id().id}")
|
|
95
|
+
# utils.sigtrap(utils.thread_id())
|
|
96
|
+
self.writer(utils.thread_id())
|
|
97
|
+
# utils.sigtrap(utils.thread_id())
|
|
98
|
+
|
|
99
|
+
write = utils.observer(on_call = utils.thread_switch_monitor(on_switch), function = self.writer)
|
|
100
|
+
|
|
94
101
|
# w = self.writer.handle('TRACE')
|
|
95
102
|
# def trace_writer(*args):
|
|
96
103
|
# print(f'Trace: {args}')
|
|
@@ -102,39 +109,50 @@ class RecordProxySystem(ProxySystem):
|
|
|
102
109
|
|
|
103
110
|
serialize = functional.walker(self.bindings.get_else_key)
|
|
104
111
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
# def on_switch():
|
|
113
|
+
# print("On thread switch!!!")
|
|
114
|
+
# # utils.sigtrap(utils.thread_id())
|
|
115
|
+
# utils.thread_id()()
|
|
116
|
+
# # utils.sigtrap(utils.thread_id())
|
|
117
|
+
|
|
118
|
+
# self.thread_switch_monitor = utils.thread_switch_monitor(on_switch)
|
|
119
|
+
|
|
120
|
+
# self.thread_switch_monitor = utils.thread_switch_monitor(functional.repeatedly(utils.thread_id))
|
|
108
121
|
|
|
109
122
|
# self.sync = lambda function: functional.firstof(self.thread_switch_monitor, functional.always(self.writer.handle('SYNC')), function)
|
|
110
|
-
|
|
123
|
+
|
|
124
|
+
self.sync = lambda function: \
|
|
125
|
+
utils.observer(
|
|
126
|
+
on_call = functional.lazy(write, self.writer.handle('SYNC')),
|
|
127
|
+
function = function)
|
|
128
|
+
|
|
111
129
|
error = self.writer.handle('ERROR')
|
|
112
130
|
|
|
113
131
|
def write_error(cls, val, traceback):
|
|
114
|
-
error
|
|
132
|
+
write(error, cls, val)
|
|
115
133
|
|
|
116
134
|
# self.set_thread_id = functional.partial(utils.set_thread_id, self.writer)
|
|
117
135
|
|
|
118
|
-
def watch(f): return functional.either(self.thread_switch_monitor, f)
|
|
119
|
-
|
|
120
136
|
# w = self.writer.handle('TRACE')
|
|
121
137
|
# def foo(name, *args):
|
|
122
138
|
# print(f'writing: {self.writer.messages_written} {name} {args}')
|
|
123
139
|
# w(self.writer.messages_written, name, *args)
|
|
124
140
|
|
|
125
141
|
# tracer = Tracer(tracing_config, writer = foo)
|
|
126
|
-
tracer = Tracer(tracing_config, writer = self.writer.handle('TRACE'))
|
|
142
|
+
tracer = Tracer(tracing_config, writer = functional.partial(write, self.writer.handle('TRACE')))
|
|
127
143
|
|
|
128
|
-
self.wrap_int_to_ext =
|
|
144
|
+
# self.wrap_int_to_ext = self.sync
|
|
129
145
|
|
|
130
|
-
self.on_int_call = functional.mapargs(transform = serialize, function = self.writer.handle('CALL'))
|
|
146
|
+
self.on_int_call = functional.mapargs(transform = serialize, function = functional.partial(write, self.writer.handle('CALL')))
|
|
131
147
|
|
|
132
|
-
self.on_ext_result = functional.sequence(serialize, self.writer.handle('RESULT'))
|
|
148
|
+
self.on_ext_result = functional.sequence(serialize, functional.partial(write, self.writer.handle('RESULT')))
|
|
133
149
|
|
|
134
150
|
self.on_ext_error = write_error
|
|
135
151
|
|
|
136
152
|
self.ext_apply = self.int_apply = functional.apply
|
|
137
153
|
|
|
154
|
+
self.writer.type_serializer[types.ModuleType] = GlobalRef
|
|
155
|
+
|
|
138
156
|
super().__init__(thread_state = thread_state,
|
|
139
157
|
tracer = tracer,
|
|
140
158
|
immutable_types = immutable_types)
|
retracesoftware/proxy/replay.py
CHANGED
|
@@ -8,7 +8,8 @@ from retracesoftware.proxy.proxytype import *
|
|
|
8
8
|
# from retracesoftware.proxy.gateway import gateway_pair
|
|
9
9
|
from retracesoftware.proxy.record import StubRef, Placeholder
|
|
10
10
|
from retracesoftware.proxy.proxysystem import ProxySystem, RetraceError
|
|
11
|
-
from retracesoftware.proxy.stubfactory import StubFactory, StubFunction
|
|
11
|
+
from retracesoftware.proxy.stubfactory import StubFactory, Stub, StubFunction
|
|
12
|
+
from retracesoftware.proxy.globalref import GlobalRef
|
|
12
13
|
|
|
13
14
|
import os
|
|
14
15
|
import weakref
|
|
@@ -153,12 +154,16 @@ class ReplayProxySystem(ProxySystem):
|
|
|
153
154
|
def read_required(self, required):
|
|
154
155
|
obj = self.readnext()
|
|
155
156
|
if obj != required:
|
|
157
|
+
print('---------------------------------')
|
|
158
|
+
print('last matching stack')
|
|
159
|
+
print('---------------------------------')
|
|
156
160
|
if self.last_matching_stack:
|
|
157
161
|
for line in self.last_matching_stack:
|
|
158
162
|
print(line)
|
|
159
163
|
|
|
160
164
|
print('---------------------------------')
|
|
161
165
|
print(f'Replay: {required}')
|
|
166
|
+
print('---------------------------------')
|
|
162
167
|
for line in utils.stacktrace():
|
|
163
168
|
print(line)
|
|
164
169
|
print('---------------------------------')
|
|
@@ -196,9 +201,6 @@ class ReplayProxySystem(ProxySystem):
|
|
|
196
201
|
for arg in args:
|
|
197
202
|
self.read_required(arg)
|
|
198
203
|
|
|
199
|
-
def sync(self, function):
|
|
200
|
-
return utils.observer(on_call = functional.always(self.read_sync), function = function)
|
|
201
|
-
|
|
202
204
|
def __init__(self,
|
|
203
205
|
thread_state,
|
|
204
206
|
immutable_types,
|
|
@@ -210,25 +212,44 @@ class ReplayProxySystem(ProxySystem):
|
|
|
210
212
|
self.reader = stream.reader(path)
|
|
211
213
|
|
|
212
214
|
self.bindings = utils.id_dict()
|
|
213
|
-
self.set_thread_id = utils.set_thread_id
|
|
215
|
+
# self.set_thread_id = utils.set_thread_id
|
|
214
216
|
self.fork_path = fork_path
|
|
215
217
|
deserialize = functional.walker(self.bindings.get_else_key)
|
|
216
218
|
|
|
217
219
|
# def count(res):
|
|
218
220
|
# self.messages_read += 1
|
|
219
221
|
# return res
|
|
222
|
+
|
|
223
|
+
read_res = functional.vector(functional.lazy(getattr, self.reader, 'messages_read'), self.reader)
|
|
224
|
+
|
|
225
|
+
def foo():
|
|
226
|
+
try:
|
|
227
|
+
messages_read, res = read_res()
|
|
228
|
+
if issubclass(type(res), Stub):
|
|
229
|
+
print(f'res: {utils.thread_id()} {messages_read} stub: {type(res)}')
|
|
230
|
+
else:
|
|
231
|
+
print(f'res: {utils.thread_id()} {messages_read} {res}')
|
|
232
|
+
|
|
233
|
+
return res
|
|
234
|
+
except Exception as error:
|
|
235
|
+
print(f'Error reading next result: {error}')
|
|
236
|
+
raise(error)
|
|
220
237
|
|
|
221
|
-
self.messages = functional.sequence(per_thread_messages(
|
|
222
|
-
|
|
238
|
+
self.messages = functional.sequence(per_thread_messages(foo), deserialize)
|
|
239
|
+
|
|
240
|
+
# self.messages = functional.sequence(per_thread_messages(self.reader), deserialize)
|
|
223
241
|
|
|
224
242
|
self.stub_factory = StubFactory(thread_state = thread_state, next_result = self.next_result)
|
|
225
243
|
|
|
226
244
|
self.last_matching_stack = None
|
|
227
245
|
|
|
228
246
|
self.reader.type_deserializer[StubRef] = self.stub_factory
|
|
247
|
+
self.reader.type_deserializer[GlobalRef] = lambda ref: ref()
|
|
229
248
|
|
|
230
|
-
|
|
231
|
-
|
|
249
|
+
read_sync = functional.lazy(self.read_required, 'SYNC')
|
|
250
|
+
|
|
251
|
+
self.sync = lambda function: utils.observer(on_call = read_sync, function = function)
|
|
252
|
+
|
|
232
253
|
super().__init__(thread_state = thread_state,
|
|
233
254
|
tracer = Tracer(tracing_config, writer = self.trace_writer),
|
|
234
255
|
immutable_types = immutable_types)
|
retracesoftware/proxy/thread.py
CHANGED
|
@@ -11,17 +11,28 @@ class ThreadSwitch:
|
|
|
11
11
|
def __init__(self, id):
|
|
12
12
|
self.id = id
|
|
13
13
|
|
|
14
|
-
def
|
|
15
|
-
|
|
14
|
+
def __repr__(self):
|
|
15
|
+
return f'ThreadSwitch<{self.id}>'
|
|
16
|
+
|
|
17
|
+
def __str__(self):
|
|
18
|
+
return f'ThreadSwitch<{self.id}>'
|
|
19
|
+
|
|
20
|
+
# def set_thread_id(writer, id):
|
|
21
|
+
# utils.sigtrap(id)
|
|
22
|
+
# utils.set_thread_id(writer.handle(ThreadSwitch(id)))
|
|
16
23
|
|
|
17
24
|
def write_thread_switch(writer):
|
|
18
25
|
on_thread_switch = functional.repeatedly(functional.sequence(utils.thread_id, writer))
|
|
19
26
|
|
|
20
27
|
return lambda f: utils.thread_aware_proxy(target = f, on_thread_switch = on_thread_switch, sticky = False)
|
|
21
28
|
|
|
22
|
-
def prefix_with_thread_id(f,
|
|
29
|
+
def prefix_with_thread_id(f, thread_id):
|
|
30
|
+
current = None
|
|
31
|
+
|
|
23
32
|
def next():
|
|
24
33
|
nonlocal current, f
|
|
34
|
+
if current is None: current = thread_id()
|
|
35
|
+
|
|
25
36
|
obj = f()
|
|
26
37
|
|
|
27
38
|
while issubclass(type(obj), ThreadSwitch):
|
|
@@ -36,7 +47,8 @@ def per_thread_messages(messages):
|
|
|
36
47
|
thread_id = utils.thread_id
|
|
37
48
|
# thread_id = lambda: 'FOOOOO!!!'
|
|
38
49
|
|
|
39
|
-
demux = utils.demux(source = prefix_with_thread_id(messages, thread_id
|
|
50
|
+
demux = utils.demux(source = prefix_with_thread_id(messages, thread_id),
|
|
51
|
+
key_function = lambda obj: obj[0])
|
|
40
52
|
|
|
41
53
|
# def next():
|
|
42
54
|
# thread,message = demux(thread_id())
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
retracesoftware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
retracesoftware/config.json,sha256=
|
|
2
|
+
retracesoftware/config.json,sha256=JU3LYWZbqBLqiHXDc9fBYVh0owMUcKGw3W-vaVm-roo,9024
|
|
3
3
|
retracesoftware/config.yaml,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
retracesoftware/install/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
retracesoftware/install/config.py,sha256=EzE5ifQF2lo--hu2njI4T0FJ-zlnWDJV6i7x0DMkVTw,1364
|
|
6
6
|
retracesoftware/install/edgecases.py,sha256=NR3lyvad9sRsyeDv_Ya8V4xMgPsMPOi9rMcnFOJGOEA,6330
|
|
7
7
|
retracesoftware/install/globals.py,sha256=F8XvIoZQQ10gSRalk30dvdKllxlwxkaggYY6FogLDxY,510
|
|
8
8
|
retracesoftware/install/install.py,sha256=HCD_ji8XCr96b5fNzNdL_8qcEp0Jf05Em7T6GA6u8HU,4969
|
|
9
|
-
retracesoftware/install/patcher.py,sha256=
|
|
9
|
+
retracesoftware/install/patcher.py,sha256=ryX73_KjdcUCC0oy0Uqel_L3bwfZZldS3CIYQ-XAl_k,20520
|
|
10
10
|
retracesoftware/install/predicate.py,sha256=tX7NQc0rGkyyHYO3mduYHcJHbw1wczT53m_Dpkzo6do,2679
|
|
11
|
-
retracesoftware/install/record.py,sha256=
|
|
11
|
+
retracesoftware/install/record.py,sha256=R2GOIA_WAggrNmVwZJh9r1xp-GVu43iKq-ykQ1VKEHE,3408
|
|
12
12
|
retracesoftware/install/references.py,sha256=A-G651IDOfuo00MkbAdpbIQh_15ChvJ7uAVTSmE6zd4,1721
|
|
13
13
|
retracesoftware/install/replay.py,sha256=VUiHvQK3mgAJEGmtE2TFs9kXzxdWtsjibEcGkhZVCVE,1830
|
|
14
14
|
retracesoftware/install/tracer.py,sha256=cHEjiVxIp2iVTJEWndwSbMuiXVyGJQxJYZSGrfpSbCw,5723
|
|
15
15
|
retracesoftware/install/typeutils.py,sha256=_a1PuwdCsYjG1Nkd77V-flqYtwbD4RkJVKn6Z-xABL4,1813
|
|
16
|
-
retracesoftware/proxy/__init__.py,sha256=
|
|
16
|
+
retracesoftware/proxy/__init__.py,sha256=ntIyqKhBRkKEkcW_oOPodikh-mxYl8OXRnSaj-9-Xwc,178
|
|
17
17
|
retracesoftware/proxy/gateway.py,sha256=xESohWXkiNm4ZutU0RgWUwxjxcBWRQ4rQyxIGQXv_F4,1590
|
|
18
|
+
retracesoftware/proxy/globalref.py,sha256=yXtJsOeBHN9xoEgJWA3MJco-jD2SQUef_fDatA4A6rg,803
|
|
18
19
|
retracesoftware/proxy/proxyfactory.py,sha256=qhOqDfMJnLDNkQs26JqDB431MwjjRhGQi8xupJ45asg,12272
|
|
19
20
|
retracesoftware/proxy/proxysystem.py,sha256=ZX6eNT8go-YDbLWD2pq5j_V8DZAHteu-iNfkMO8jLWg,7567
|
|
20
|
-
retracesoftware/proxy/proxytype.py,sha256=
|
|
21
|
-
retracesoftware/proxy/record.py,sha256=
|
|
22
|
-
retracesoftware/proxy/replay.py,sha256=
|
|
21
|
+
retracesoftware/proxy/proxytype.py,sha256=hP-1vJmWBa9KgZFB3CnZy0UbC4u8Wr2e76lGI0JM2SA,12992
|
|
22
|
+
retracesoftware/proxy/record.py,sha256=QBx3G8mXjUiB9vCXJZ0tZdt3Mi1WEtRhuZ7HOUroNNQ,5505
|
|
23
|
+
retracesoftware/proxy/replay.py,sha256=vVFkhYOOZSprLD_mjx-p6SpDB8fy81SK3x2A5H0odUs,8614
|
|
23
24
|
retracesoftware/proxy/stubfactory.py,sha256=37UX1r8HCAbASTwPdz8QKCrg72NQmM5PsiCho7N2nzg,5129
|
|
24
|
-
retracesoftware/proxy/thread.py,sha256
|
|
25
|
-
retracesoftware_proxy-0.1.
|
|
26
|
-
retracesoftware_proxy-0.1.
|
|
27
|
-
retracesoftware_proxy-0.1.
|
|
28
|
-
retracesoftware_proxy-0.1.
|
|
25
|
+
retracesoftware/proxy/thread.py,sha256=idkJwJ8rR1kpRHfo81uCi6Y0LEIChAdfc0GqK_bFqTA,1635
|
|
26
|
+
retracesoftware_proxy-0.1.14.dist-info/METADATA,sha256=Y6QfA5aDmUke1rEvUWSOgRIwbEAk7YbbcpW-7m00kQM,203
|
|
27
|
+
retracesoftware_proxy-0.1.14.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
28
|
+
retracesoftware_proxy-0.1.14.dist-info/top_level.txt,sha256=hYHsR6txLidmqvjBMITpIHvmJJbmoCAgr76-IpZPRz8,16
|
|
29
|
+
retracesoftware_proxy-0.1.14.dist-info/RECORD,,
|
|
File without changes
|
{retracesoftware_proxy-0.1.13.dist-info → retracesoftware_proxy-0.1.14.dist-info}/top_level.txt
RENAMED
|
File without changes
|