retracesoftware-proxy 0.0.0__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/__init__.py +0 -0
- retracesoftware/__main__.py +266 -0
- retracesoftware/autoenable.py +53 -0
- retracesoftware/config.json +175 -0
- retracesoftware/config.yaml +0 -0
- retracesoftware/install/__init__.py +0 -0
- retracesoftware/install/config.py +59 -0
- retracesoftware/install/edgecases.py +242 -0
- retracesoftware/install/globals.py +17 -0
- retracesoftware/install/install.py +142 -0
- retracesoftware/install/patcher.py +122 -0
- retracesoftware/install/patchfindspec.py +117 -0
- retracesoftware/install/phases.py +338 -0
- retracesoftware/install/predicate.py +92 -0
- retracesoftware/install/record.py +174 -0
- retracesoftware/install/references.py +66 -0
- retracesoftware/install/replace.py +28 -0
- retracesoftware/install/replay.py +102 -0
- retracesoftware/install/tracer.py +284 -0
- retracesoftware/install/typeutils.py +92 -0
- retracesoftware/modules.toml +384 -0
- retracesoftware/proxy/__init__.py +3 -0
- retracesoftware/proxy/gateway.py +49 -0
- retracesoftware/proxy/globalref.py +31 -0
- retracesoftware/proxy/messagestream.py +204 -0
- retracesoftware/proxy/proxyfactory.py +357 -0
- retracesoftware/proxy/proxysystem.py +454 -0
- retracesoftware/proxy/proxytype.py +424 -0
- retracesoftware/proxy/record.py +211 -0
- retracesoftware/proxy/replay.py +138 -0
- retracesoftware/proxy/serializer.py +28 -0
- retracesoftware/proxy/startthread.py +40 -0
- retracesoftware/proxy/stubfactory.py +195 -0
- retracesoftware/proxy/thread.py +106 -0
- retracesoftware/replay.py +104 -0
- retracesoftware/run.py +373 -0
- retracesoftware/stackdifference.py +133 -0
- retracesoftware_proxy-0.0.0.dist-info/METADATA +8 -0
- retracesoftware_proxy-0.0.0.dist-info/RECORD +41 -0
- retracesoftware_proxy-0.0.0.dist-info/WHEEL +5 -0
- retracesoftware_proxy-0.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
from retracesoftware_utils import counter
|
|
2
|
+
from retracesoftware_functional import *
|
|
3
|
+
|
|
4
|
+
import types
|
|
5
|
+
import pickle
|
|
6
|
+
import gc
|
|
7
|
+
import os
|
|
8
|
+
import functools
|
|
9
|
+
import inspect
|
|
10
|
+
|
|
11
|
+
def is_function_type(cls):
|
|
12
|
+
return issubclass(cls, types.BuiltinFunctionType) or issubclass(cls, types.FunctionType)
|
|
13
|
+
|
|
14
|
+
def superdict(cls):
|
|
15
|
+
result = {}
|
|
16
|
+
for cls in list(reversed(cls.__mro__))[1:]:
|
|
17
|
+
result.update(cls.__dict__)
|
|
18
|
+
|
|
19
|
+
return result
|
|
20
|
+
|
|
21
|
+
def is_method_descriptor(obj):
|
|
22
|
+
return isinstance(obj, types.FunctionType) or \
|
|
23
|
+
(isinstance(obj, (types.WrapperDescriptorType, types.MethodDescriptorType)) and obj.__objclass__ != object)
|
|
24
|
+
|
|
25
|
+
def blacklist_for(self, cls):
|
|
26
|
+
return ['__getattribute__', '__hash__', '__del__', '__init__', '__call__']
|
|
27
|
+
|
|
28
|
+
def is_descriptor(obj):
|
|
29
|
+
return hasattr(obj, '__get__') or hasattr(obj, '__set__') or hasattr(obj, '__delete__')
|
|
30
|
+
|
|
31
|
+
def methods(cls):
|
|
32
|
+
for name,value in superdict(cls).items():
|
|
33
|
+
if is_descriptor(value) and is_method_descriptor(value):
|
|
34
|
+
yield name
|
|
35
|
+
|
|
36
|
+
def patch_spec(cls, blacklist):
|
|
37
|
+
return {
|
|
38
|
+
'name': f'retrace.proxied.{cls.__module__}.{cls.__name__}',
|
|
39
|
+
'methods': [m for m in methods(cls) if m not in blacklist],
|
|
40
|
+
'callable': yeilds_callable_instances(cls),
|
|
41
|
+
'weakrefs': yeilds_weakly_referenceable_instances(cls)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
def proxytype_from_spec(target_for, spec):
|
|
45
|
+
proxytype = create_wrapping_proxy_type(
|
|
46
|
+
name = spec['name'],
|
|
47
|
+
callable = spec['callable'],
|
|
48
|
+
weakrefs = spec['weakrefs'])
|
|
49
|
+
|
|
50
|
+
def add_method_descriptor(name, target):
|
|
51
|
+
setattr(proxytype, name, proxytype.method_descriptor(name = name, target = target))
|
|
52
|
+
|
|
53
|
+
for method in spec['methods']:
|
|
54
|
+
add_method_descriptor(name = method, target = target_for(method))
|
|
55
|
+
|
|
56
|
+
# add_method_descriptor(name = '__getattr__', target = object.__getattribute__)
|
|
57
|
+
add_method_descriptor(name = '__getattr__', target = getattr)
|
|
58
|
+
add_method_descriptor(name = '__setattr__', target = setattr)
|
|
59
|
+
|
|
60
|
+
return proxytype
|
|
61
|
+
|
|
62
|
+
def stubtype_from_spec(spec):
|
|
63
|
+
proxytype = create_stub_proxy_type(
|
|
64
|
+
name = spec['name'],
|
|
65
|
+
callable = spec['callable'],
|
|
66
|
+
weakrefs = spec['weakrefs'])
|
|
67
|
+
|
|
68
|
+
def add_method_descriptor(name):
|
|
69
|
+
setattr(proxytype, name, proxytype.method_descriptor(name))
|
|
70
|
+
|
|
71
|
+
for method in spec['methods']:
|
|
72
|
+
add_method_descriptor(method)
|
|
73
|
+
|
|
74
|
+
add_method_descriptor('__getattr__')
|
|
75
|
+
add_method_descriptor('__setattr__')
|
|
76
|
+
|
|
77
|
+
return proxytype
|
|
78
|
+
|
|
79
|
+
def wrap_method_descriptors(wrapper, prefix, base):
|
|
80
|
+
slots = {"__slots__": () }
|
|
81
|
+
|
|
82
|
+
extended = type(f'{prefix}.{base.__module__}.{base.__name__}', (base,), {"__slots__": () })
|
|
83
|
+
|
|
84
|
+
blacklist = ['__getattribute__', '__hash__', '__del__']
|
|
85
|
+
|
|
86
|
+
for name,value in superdict(base).items():
|
|
87
|
+
if name not in blacklist:
|
|
88
|
+
if is_method_descriptor(value):
|
|
89
|
+
setattr(extended, name, wrapper(value))
|
|
90
|
+
|
|
91
|
+
return extended
|
|
92
|
+
|
|
93
|
+
def sync_type(sync, base):
|
|
94
|
+
return wrap_method_descriptors(
|
|
95
|
+
wrapper = lambda desc: intercept(on_call = sync, function = desc),
|
|
96
|
+
prefix = 'retrace.synced',
|
|
97
|
+
base = base)
|
|
98
|
+
|
|
99
|
+
class GCHook:
|
|
100
|
+
def __init__(self, thread_state):
|
|
101
|
+
self.thread_state = thread_state
|
|
102
|
+
|
|
103
|
+
def __call__(self, phase, info):
|
|
104
|
+
if phase == 'start':
|
|
105
|
+
self.saved_state = self.thread_state.value
|
|
106
|
+
self.thread_state.value = 'disabled'
|
|
107
|
+
|
|
108
|
+
elif phase == 'stop':
|
|
109
|
+
self.thread_state.value = self.saved_state
|
|
110
|
+
|
|
111
|
+
# class ProxyFactory:
|
|
112
|
+
|
|
113
|
+
# def ext_proxy_factory(self):
|
|
114
|
+
# return wrapping_proxy_factory(proxytype = self.proxytype, create_reference = compose(type, Reference), handler = self.ext_handler)
|
|
115
|
+
|
|
116
|
+
# def int_proxy_factory(self):
|
|
117
|
+
# return wrapping_proxy_factory(proxytype = self.proxytype, create_reference = Reference, handler = self.int_handler)
|
|
118
|
+
|
|
119
|
+
# def ext_call_handler(self):
|
|
120
|
+
# return self.int_handler.call_handler
|
|
121
|
+
|
|
122
|
+
# def int_call_handler(self):
|
|
123
|
+
# return self.ext_handler.call_handler
|
|
124
|
+
|
|
125
|
+
# def before_fork(self):
|
|
126
|
+
# pass
|
|
127
|
+
# # self.state_before_fork = self.thread_state.value
|
|
128
|
+
# # self.thread_state.value = 'disabled'
|
|
129
|
+
|
|
130
|
+
# def after_fork_in_child(self):
|
|
131
|
+
# self.fork_counter = 0
|
|
132
|
+
|
|
133
|
+
# def after_fork_in_parent(self):
|
|
134
|
+
# self.fork_counter += 1
|
|
135
|
+
# # self.thread_state.value = self.state_before_fork
|
|
136
|
+
|
|
137
|
+
# def gc_start(self):
|
|
138
|
+
# self.before_gc = self.thread_state.value
|
|
139
|
+
# self.thread_state.value = 'external'
|
|
140
|
+
|
|
141
|
+
# def gc_end(self):
|
|
142
|
+
# self.thread_state.value = self.before_gc
|
|
143
|
+
# del self.before_gc
|
|
144
|
+
|
|
145
|
+
# def gc_hook(self, phase, info):
|
|
146
|
+
|
|
147
|
+
# if phase == 'start':
|
|
148
|
+
# self.gc_start()
|
|
149
|
+
|
|
150
|
+
# elif phase == 'stop':
|
|
151
|
+
# self.gc_end()
|
|
152
|
+
|
|
153
|
+
# def __init__(self, thread_state, on_new_proxytype, sync,
|
|
154
|
+
# debug, checkpoint, verbose,
|
|
155
|
+
# ext_proxy, ext_handler, int_proxy, int_handler):
|
|
156
|
+
|
|
157
|
+
# assert ext_proxy
|
|
158
|
+
|
|
159
|
+
# self.ext_proxy = ext_proxy
|
|
160
|
+
# self.ext_handler = ext_handler
|
|
161
|
+
# self.int_proxy = int_proxy
|
|
162
|
+
# self.int_handler = int_handler
|
|
163
|
+
|
|
164
|
+
# def normalize(obj):
|
|
165
|
+
# if isinstance(obj, RootProxy):
|
|
166
|
+
# return str(obj)
|
|
167
|
+
# elif isinstance(obj, MethodDescriptor):
|
|
168
|
+
# return f'{obj.__objclass__.__module__}.{obj.__objclass__.__name__}.{obj.__name__}'
|
|
169
|
+
# elif isinstance(obj, Proxy):
|
|
170
|
+
# return 'Proxy'
|
|
171
|
+
# else:
|
|
172
|
+
# return obj
|
|
173
|
+
|
|
174
|
+
# self.normalize = walker(normalize)
|
|
175
|
+
|
|
176
|
+
# self.checkpoint_ext_call = mapargs(transform = self.normalize,
|
|
177
|
+
# function = self.checkpoint_ext_call)
|
|
178
|
+
|
|
179
|
+
# # self.checkpoint_ext_call = self.arg_serializer(self.checkpoint_ext_call)
|
|
180
|
+
|
|
181
|
+
# self.thread_state = thread_state
|
|
182
|
+
# self.debug = debug
|
|
183
|
+
# self.fork_counter = 0
|
|
184
|
+
# self.verbose = verbose
|
|
185
|
+
|
|
186
|
+
# self.on_new_proxytype = on_new_proxytype
|
|
187
|
+
# self._sync = sync
|
|
188
|
+
# self.thread_counter = self.sync_function(counter(1))
|
|
189
|
+
|
|
190
|
+
# # immutable_types = self.disable_for(immutable_types)
|
|
191
|
+
|
|
192
|
+
# gc.callbacks.append(self.gc_hook)
|
|
193
|
+
|
|
194
|
+
# def before():
|
|
195
|
+
# print("In before!!!!")
|
|
196
|
+
# with self.thread_state.select('disabled'):
|
|
197
|
+
# self.before_fork()
|
|
198
|
+
|
|
199
|
+
# os.register_at_fork(
|
|
200
|
+
# # before = self.thread_state.wrap('disabled', self.before_fork),
|
|
201
|
+
# before = before,
|
|
202
|
+
# after_in_parent = self.thread_state.wrap('disabled', self.after_fork_in_parent),
|
|
203
|
+
# after_in_child = self.thread_state.wrap('disabled', self.after_fork_in_child))
|
|
204
|
+
|
|
205
|
+
# self.tracing = None
|
|
206
|
+
|
|
207
|
+
# if debug > 3:
|
|
208
|
+
|
|
209
|
+
# # def checkpoint(obj):
|
|
210
|
+
# # print(f'in checkpoint: {obj}')
|
|
211
|
+
# # self.checkpoint(obj)
|
|
212
|
+
|
|
213
|
+
# FrameTracer.install(self.thread_state.dispatch(_proxy.noop, internal = checkpoint))
|
|
214
|
+
|
|
215
|
+
# # import threading
|
|
216
|
+
# # tracer = FrameTracer(
|
|
217
|
+
# # pred = self.thread_state.predicate('internal'),
|
|
218
|
+
# # checkpoint = checkpoint)
|
|
219
|
+
|
|
220
|
+
# # sys.settrace(tracer)
|
|
221
|
+
# # threading.settrace(tracer)
|
|
222
|
+
# # self.trace = lambda event, **kwargs: checkpoint({'type': 'trace', 'event': event} | kwargs)
|
|
223
|
+
# # self.enable_tracing()
|
|
224
|
+
|
|
225
|
+
# def sync_type(self, base):
|
|
226
|
+
# return sync_type(sync = self.sync, base = base)
|
|
227
|
+
|
|
228
|
+
# def sync_function(self, function):
|
|
229
|
+
# return intercept(on_call = self._sync, function = function)
|
|
230
|
+
|
|
231
|
+
# def checkpoint(self, obj):
|
|
232
|
+
# pass
|
|
233
|
+
|
|
234
|
+
# def log(self, message):
|
|
235
|
+
# if self.verbose:
|
|
236
|
+
# print(message)
|
|
237
|
+
|
|
238
|
+
# self.checkpoint({'type': 'log', 'message': message})
|
|
239
|
+
|
|
240
|
+
# @property
|
|
241
|
+
# def disable(self):
|
|
242
|
+
# return self.thread_state.select('disabled')
|
|
243
|
+
|
|
244
|
+
# def with_state(self, state, function):
|
|
245
|
+
# return self.thread_state.wrap(desired_state = state, function = function)
|
|
246
|
+
|
|
247
|
+
# def disable_for(self, function):
|
|
248
|
+
# return self.thread_state.wrap(desired_state = 'disabled', function = function)
|
|
249
|
+
|
|
250
|
+
# def __call__(self, module, name, obj):
|
|
251
|
+
|
|
252
|
+
# if type(obj) == type:
|
|
253
|
+
# try:
|
|
254
|
+
# return self.extend_type(obj)
|
|
255
|
+
# except:
|
|
256
|
+
# pass
|
|
257
|
+
|
|
258
|
+
# self.checkpoint({'type': 'proxy', 'module': module, 'name': name})
|
|
259
|
+
|
|
260
|
+
# if is_function_type(type(obj)) or type(obj) == type:
|
|
261
|
+
# proxied = RootProxy(module = module, name = name, handler = self.ext_handler, target = obj)
|
|
262
|
+
|
|
263
|
+
# try:
|
|
264
|
+
# # print(f"signature: {inspect.signature(obj)} for {obj}")
|
|
265
|
+
# proxied.__signature__ = inspect.signature(obj)
|
|
266
|
+
# except:
|
|
267
|
+
# pass
|
|
268
|
+
|
|
269
|
+
# return proxied
|
|
270
|
+
# else:
|
|
271
|
+
# return self.ext_proxy(obj)
|
|
272
|
+
|
|
273
|
+
# # return self.ext_proxy(obj)
|
|
274
|
+
|
|
275
|
+
# def start_new_thread(self, start_new_thread, function, *args):
|
|
276
|
+
# # synchronized, replay shoudl yeild correct number
|
|
277
|
+
# thread_id = self.thread_counter()
|
|
278
|
+
|
|
279
|
+
# def threadrunner(*args, **kwargs):
|
|
280
|
+
# self.set_thread_number(thread_id)
|
|
281
|
+
# with self.thread_state.select('internal'):
|
|
282
|
+
# if self.tracing:
|
|
283
|
+
# FrameTracer.install(self.thread_state.dispatch(noop, internal = self.checkpoint))
|
|
284
|
+
|
|
285
|
+
# return function(*args, **kwargs)
|
|
286
|
+
|
|
287
|
+
# return start_new_thread(threadrunner, *args)
|
|
288
|
+
|
|
289
|
+
# def wrap_start_new_thread(self, start_new_thread):
|
|
290
|
+
# wrapped = functools.partial(self.start_new_thread, start_new_thread)
|
|
291
|
+
# return self.thread_state.dispatch(start_new_thread, internal = wrapped)
|
|
292
|
+
|
|
293
|
+
# def checkpoint_ext_call(self, func, *args, **kwargs):
|
|
294
|
+
# self.checkpoint({'type':
|
|
295
|
+
# 'external.call',
|
|
296
|
+
# 'function': str(func)})
|
|
297
|
+
|
|
298
|
+
# def extend_type(self, base):
|
|
299
|
+
|
|
300
|
+
# assert not issubclass(base, BaseException)
|
|
301
|
+
|
|
302
|
+
# self.checkpoint({'type': 'log', 'message': f'extending type: {base}'})
|
|
303
|
+
|
|
304
|
+
# def custom_init_subclass(cls, **kwargs):
|
|
305
|
+
# for name, target in cls.__dict__.items():
|
|
306
|
+
# if is_method_descriptor(target):
|
|
307
|
+
# proxied = cls.method_descriptor(handler = self.int_handler,
|
|
308
|
+
# call_handler = self.thread_state.predicate('external'),
|
|
309
|
+
# name = name,
|
|
310
|
+
# target = target)
|
|
311
|
+
# setattr(cls, name, proxied)
|
|
312
|
+
|
|
313
|
+
# def __new__(cls, *args, **kwargs):
|
|
314
|
+
# instance = base.__new__(cls, *args, **kwargs)
|
|
315
|
+
# self.on_new(instance)
|
|
316
|
+
# return instance
|
|
317
|
+
|
|
318
|
+
# slots = {
|
|
319
|
+
# "__slots__": (),
|
|
320
|
+
# '__new__': __new__,
|
|
321
|
+
# "__init_subclass__": classmethod(custom_init_subclass)
|
|
322
|
+
# }
|
|
323
|
+
|
|
324
|
+
# extended = type(f'retrace.extended.{base.__module__}.{base.__name__}', (base, _proxy.ExtendedProxy), slots)
|
|
325
|
+
|
|
326
|
+
# blacklist = ['__getattribute__', '__hash__', '__del__']
|
|
327
|
+
|
|
328
|
+
# for name,value in superdict(base).items():
|
|
329
|
+
# if name not in blacklist:
|
|
330
|
+
# if is_method_descriptor(value):
|
|
331
|
+
# proxied = extended.method_descriptor(
|
|
332
|
+
# handler = self.ext_handler,
|
|
333
|
+
# name = name,
|
|
334
|
+
# target = getattr(base, name))
|
|
335
|
+
|
|
336
|
+
# setattr(extended, name, proxied)
|
|
337
|
+
# elif is_descriptor(value):
|
|
338
|
+
# setattr(extended, name, self.ext_proxy(value))
|
|
339
|
+
|
|
340
|
+
# def __del__(obj):
|
|
341
|
+
# try:
|
|
342
|
+
# self.on_del(Reference(obj))
|
|
343
|
+
# # self.external.handler.on_del(_proxy.Reference(obj))
|
|
344
|
+
# except:
|
|
345
|
+
# pass
|
|
346
|
+
|
|
347
|
+
# try:
|
|
348
|
+
# base.__del__(obj)
|
|
349
|
+
# except:
|
|
350
|
+
# pass
|
|
351
|
+
|
|
352
|
+
# extended.__del__ = __del__
|
|
353
|
+
|
|
354
|
+
# if self.on_new_proxytype:
|
|
355
|
+
# self.on_new_proxytype(base.__module__, base.__name__, extended)
|
|
356
|
+
|
|
357
|
+
# return extended
|