retracesoftware-proxy 0.1.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/config.json +382 -0
- retracesoftware/install/__init__.py +0 -0
- retracesoftware/install/config.py +53 -0
- retracesoftware/install/edgecases.py +220 -0
- retracesoftware/install/globals.py +17 -0
- retracesoftware/install/install.py +172 -0
- retracesoftware/install/patcher.py +494 -0
- retracesoftware/install/predicate.py +92 -0
- retracesoftware/install/record.py +128 -0
- retracesoftware/install/references.py +65 -0
- retracesoftware/install/replay.py +151 -0
- retracesoftware/install/tracer.py +144 -0
- retracesoftware/install/typeutils.py +72 -0
- retracesoftware/proxy/__init__.py +3 -0
- retracesoftware/proxy/gateway.py +100 -0
- retracesoftware/proxy/proxyfactory.py +357 -0
- retracesoftware/proxy/proxysystem.py +20 -0
- retracesoftware/proxy/proxytype.py +280 -0
- retracesoftware/proxy/record.py +133 -0
- retracesoftware/proxy/replay.py +110 -0
- retracesoftware/proxy/thread.py +11 -0
- retracesoftware_proxy-0.1.0.dist-info/METADATA +12 -0
- retracesoftware_proxy-0.1.0.dist-info/RECORD +26 -0
- retracesoftware_proxy-0.1.0.dist-info/WHEEL +5 -0
- retracesoftware_proxy-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import retracesoftware_utils as utils
|
|
2
|
+
import retracesoftware.functional as functional
|
|
3
|
+
|
|
4
|
+
import types
|
|
5
|
+
|
|
6
|
+
class Proxy:
|
|
7
|
+
__slots__ = []
|
|
8
|
+
|
|
9
|
+
class Stub(Proxy):
|
|
10
|
+
__slots__ = []
|
|
11
|
+
|
|
12
|
+
class DynamicProxy(Proxy):
|
|
13
|
+
__slots__ = []
|
|
14
|
+
|
|
15
|
+
class ExtendingProxy(Proxy):
|
|
16
|
+
__slots__ = []
|
|
17
|
+
|
|
18
|
+
class InternalProxy:
|
|
19
|
+
__slots__ = []
|
|
20
|
+
|
|
21
|
+
def superdict(cls):
|
|
22
|
+
result = {}
|
|
23
|
+
for cls in list(reversed(cls.__mro__))[1:]:
|
|
24
|
+
result.update(cls.__dict__)
|
|
25
|
+
|
|
26
|
+
return result
|
|
27
|
+
|
|
28
|
+
def is_method_descriptor(obj):
|
|
29
|
+
return isinstance(obj, types.FunctionType) or \
|
|
30
|
+
(isinstance(obj, (types.WrapperDescriptorType, types.MethodDescriptorType)) and obj.__objclass__ != object)
|
|
31
|
+
|
|
32
|
+
def proxy_method_descriptors(cls, handler):
|
|
33
|
+
for name, target in cls.__dict__.items():
|
|
34
|
+
if is_method_descriptor(target):
|
|
35
|
+
proxied = utils.wrapped_function(handler = handler, target = target)
|
|
36
|
+
setattr(cls, name, proxied)
|
|
37
|
+
|
|
38
|
+
def methods(cls):
|
|
39
|
+
for name,value in superdict(cls).items():
|
|
40
|
+
if is_descriptor(value) and is_method_descriptor(value):
|
|
41
|
+
yield name
|
|
42
|
+
|
|
43
|
+
def is_descriptor(obj):
|
|
44
|
+
return hasattr(obj, '__get__') or hasattr(obj, '__set__') or hasattr(obj, '__delete__')
|
|
45
|
+
|
|
46
|
+
class Named:
|
|
47
|
+
def __init__(self, name):
|
|
48
|
+
self.__name__ = name
|
|
49
|
+
|
|
50
|
+
class DescriptorStub:
|
|
51
|
+
|
|
52
|
+
__slots__ = ['handler', 'name']
|
|
53
|
+
|
|
54
|
+
def __init__(self, handler, name):
|
|
55
|
+
self.handler = handler
|
|
56
|
+
self.name = name
|
|
57
|
+
|
|
58
|
+
def __get__(self, instance, owner):
|
|
59
|
+
return self.handler(Named('getattr'), self.name)
|
|
60
|
+
|
|
61
|
+
def __set__(self, instance, value):
|
|
62
|
+
return self.handler(Named('setattr'), self.name, value)
|
|
63
|
+
|
|
64
|
+
def __delete__(self, instance):
|
|
65
|
+
return self.handler(Named('delattr'), self.name)
|
|
66
|
+
|
|
67
|
+
def stubtype_from_spec(handler, module, name, methods, members):
|
|
68
|
+
|
|
69
|
+
spec = {
|
|
70
|
+
'__module__': module,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
for method in methods:
|
|
74
|
+
spec[method] = utils.wrapped_function(
|
|
75
|
+
handler = handler, target = Named(method))
|
|
76
|
+
|
|
77
|
+
for member in members:
|
|
78
|
+
spec[member] = DescriptorStub(handler = handler, name = member)
|
|
79
|
+
|
|
80
|
+
return type(name, (Stub, DynamicProxy,), spec)
|
|
81
|
+
|
|
82
|
+
# stubtype.__new__ = thread_state.dispatch(disabled__new__, internal = stub.__new__, external = stub.__new__)
|
|
83
|
+
# stub.__retrace_unproxied__ = cls
|
|
84
|
+
|
|
85
|
+
def dynamic_stubtype(handler, cls):
|
|
86
|
+
|
|
87
|
+
assert not issubclass(cls, BaseException)
|
|
88
|
+
|
|
89
|
+
blacklist = ['__getattribute__', '__hash__', '__del__', '__init__', '__call__']
|
|
90
|
+
|
|
91
|
+
to_proxy = [m for m in methods(cls) if m not in blacklist]
|
|
92
|
+
|
|
93
|
+
def wrap(name): return utils.wrapped_function(handler = handler,
|
|
94
|
+
target = Named(name))
|
|
95
|
+
|
|
96
|
+
spec = { name: wrap(name) for name in to_proxy }
|
|
97
|
+
|
|
98
|
+
spec['__getattr__'] = wrap('__getattr__')
|
|
99
|
+
spec['__setattr__'] = wrap('__setattr__')
|
|
100
|
+
|
|
101
|
+
if utils.yields_callable_instances(cls):
|
|
102
|
+
spec['__call__'] = handler
|
|
103
|
+
|
|
104
|
+
spec['__retrace_target_class__'] = cls
|
|
105
|
+
spec['__class__'] = property(functional.repeatedly(cls))
|
|
106
|
+
|
|
107
|
+
name = f'retrace.proxied.{cls.__module__}.{cls.__name__}'
|
|
108
|
+
|
|
109
|
+
return type(name, (Stub, DynamicProxy), spec)
|
|
110
|
+
|
|
111
|
+
def dynamic_proxytype(handler, cls):
|
|
112
|
+
|
|
113
|
+
assert not issubclass(cls, BaseException)
|
|
114
|
+
|
|
115
|
+
blacklist = ['__getattribute__', '__hash__', '__del__', '__init__', '__call__']
|
|
116
|
+
|
|
117
|
+
to_proxy = [m for m in methods(cls) if m not in blacklist]
|
|
118
|
+
|
|
119
|
+
def wrap(target): return utils.wrapped_function(handler = handler, target = target)
|
|
120
|
+
|
|
121
|
+
spec = { name: wrap(getattr(cls, name)) for name in to_proxy }
|
|
122
|
+
|
|
123
|
+
spec['__getattr__'] = wrap(getattr)
|
|
124
|
+
spec['__setattr__'] = wrap(setattr)
|
|
125
|
+
|
|
126
|
+
if utils.yields_callable_instances(cls):
|
|
127
|
+
spec['__call__'] = handler
|
|
128
|
+
|
|
129
|
+
spec['__retrace_target_class__'] = cls
|
|
130
|
+
|
|
131
|
+
target_type = functional.compose(utils.unwrap, functional.typeof)
|
|
132
|
+
spec['__class__'] = property(target_type)
|
|
133
|
+
|
|
134
|
+
name = f'retrace.proxied.{cls.__module__}.{cls.__name__}'
|
|
135
|
+
|
|
136
|
+
return type(name, (utils.Wrapped, DynamicProxy), spec)
|
|
137
|
+
|
|
138
|
+
def dynamic_int_proxytype(handler, cls, bind):
|
|
139
|
+
proxytype = dynamic_proxytype(handler = handler, cls = cls)
|
|
140
|
+
proxytype.__new__ = functional.sequence(proxytype.__new__, functional.side_effect(bind))
|
|
141
|
+
return proxytype
|
|
142
|
+
|
|
143
|
+
class DescriptorProxy:
|
|
144
|
+
|
|
145
|
+
__slots__ = ['handler', 'proxytype', 'name']
|
|
146
|
+
|
|
147
|
+
def __init__(self, proxytype, handler, name):
|
|
148
|
+
self.proxytype = proxytype
|
|
149
|
+
self.handler = handler
|
|
150
|
+
self.name = name
|
|
151
|
+
|
|
152
|
+
def __get__(self, instance, owner):
|
|
153
|
+
inst = owner if instance is None else instance
|
|
154
|
+
getter = functional.partial(getattr, super(self.proxytype, inst))
|
|
155
|
+
return self.handler(getter, self.name)
|
|
156
|
+
|
|
157
|
+
def __set__(self, instance, value):
|
|
158
|
+
setter = functional.partial(setattr, super(self.proxytype, instance))
|
|
159
|
+
return self.handler(setter, self.name, value)
|
|
160
|
+
|
|
161
|
+
def __delete__(self, instance):
|
|
162
|
+
deleter = functional.partial(delattr, super(self.proxytype, instance))
|
|
163
|
+
return self.handler(deleter, self.name)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
blacklist = ['__getattribute__', '__hash__', '__del__']
|
|
167
|
+
|
|
168
|
+
# if the type can be patched, thats better, all new instances must be of correct type
|
|
169
|
+
|
|
170
|
+
def extending_proxytype(cls, thread_state, ext_handler, int_handler, on_subclass_new, is_stub = False):
|
|
171
|
+
|
|
172
|
+
assert not issubclass(cls, BaseException)
|
|
173
|
+
|
|
174
|
+
def init_subclass(subclass, **kwargs):
|
|
175
|
+
print(f'In init_subclass: {subclass} {kwargs}')
|
|
176
|
+
# subclass.__retrace_unproxied__ = create_unproxied_type(subclass)
|
|
177
|
+
|
|
178
|
+
proxy_method_descriptors(cls = subclass, handler = int_handler)
|
|
179
|
+
|
|
180
|
+
if not issubclass(subclass, InternalProxy):
|
|
181
|
+
subclass.__new__ = functional.compose(subclass.__new__, functional.side_effect(on_subclass_new))
|
|
182
|
+
subclass.__bases__ = subclass.__bases__ + (InternalProxy,)
|
|
183
|
+
|
|
184
|
+
slots = { "__slots__": (), "__init_subclass__": init_subclass }
|
|
185
|
+
|
|
186
|
+
def wrap(target): return utils.wrapped_function(handler = ext_handler, target = target)
|
|
187
|
+
|
|
188
|
+
descriptors = []
|
|
189
|
+
|
|
190
|
+
for name,value in superdict(cls).items():
|
|
191
|
+
if name not in blacklist:
|
|
192
|
+
if is_method_descriptor(value):
|
|
193
|
+
slots[name] = wrap(getattr(cls, name))
|
|
194
|
+
elif is_descriptor(value):
|
|
195
|
+
descriptors.append(name)
|
|
196
|
+
|
|
197
|
+
name = f'retrace.extended.{cls.__module__}.{cls.__name__}'
|
|
198
|
+
|
|
199
|
+
extended = type(name, (cls, ExtendingProxy), slots)
|
|
200
|
+
|
|
201
|
+
for name in descriptors:
|
|
202
|
+
proxy = DescriptorProxy(handler = ext_handler, name = name, proxytype = extended)
|
|
203
|
+
setattr(extended, name, proxy)
|
|
204
|
+
|
|
205
|
+
# def disabled__new__(subcls, *args, **kwargs):
|
|
206
|
+
# print('IN Diabled new!!!')
|
|
207
|
+
|
|
208
|
+
# instance = cls.__new__(subcls.__retrace_unproxied__, *args, **kwargs)
|
|
209
|
+
# instance.__init__(*args, **kwargs)
|
|
210
|
+
# return instance
|
|
211
|
+
|
|
212
|
+
# __new__ = functional.compose(cls.__new__, functional.side_effect(on_new))
|
|
213
|
+
if is_stub:
|
|
214
|
+
def __new__(cls, *args, **kwargs):
|
|
215
|
+
instance = utils.create_stub_object(cls)
|
|
216
|
+
# print(instance is None)
|
|
217
|
+
# utils.sigtrap(None)
|
|
218
|
+
return instance
|
|
219
|
+
|
|
220
|
+
extended.__new__ = thread_state.dispatch(cls.__new__, internal = __new__, external = __new__)
|
|
221
|
+
|
|
222
|
+
# extended.__retrace_unproxied__ = cls
|
|
223
|
+
|
|
224
|
+
return extended
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def stubtype(cls, result, thread_state, handler):
|
|
228
|
+
|
|
229
|
+
name = f'retrace.stub.{cls.__module__}.{cls.__name__}'
|
|
230
|
+
|
|
231
|
+
slots = {}
|
|
232
|
+
|
|
233
|
+
def wrap(name):
|
|
234
|
+
return utils.wrapped_function(
|
|
235
|
+
handler = handler,
|
|
236
|
+
target = StubMethodDescriptor(name = name, result = result))
|
|
237
|
+
|
|
238
|
+
for name,value in superdict(cls).items():
|
|
239
|
+
if name not in blacklist:
|
|
240
|
+
if is_method_descriptor(value):
|
|
241
|
+
slots[name] = wrap(name)
|
|
242
|
+
elif is_descriptor(value):
|
|
243
|
+
slots[name] = DescriptorStub(handler = handler, name = name)
|
|
244
|
+
|
|
245
|
+
def disabled__new__(subcls, *args, **kwargs):
|
|
246
|
+
instance = cls.__new__(subcls.__retrace_unproxied__, *args, **kwargs)
|
|
247
|
+
instance.__init__(*args, **kwargs)
|
|
248
|
+
return instance
|
|
249
|
+
|
|
250
|
+
stub = type(name, (Stub,), slots)
|
|
251
|
+
|
|
252
|
+
stub.__new__ = thread_state.dispatch(disabled__new__, internal = stub.__new__, external = stub.__new__)
|
|
253
|
+
|
|
254
|
+
stub.__retrace_unproxied__ = cls
|
|
255
|
+
|
|
256
|
+
return stub
|
|
257
|
+
|
|
258
|
+
def create_unproxied_type(cls):
|
|
259
|
+
name = f'{cls.__module__}.{cls.__name__}'
|
|
260
|
+
|
|
261
|
+
def unproxy_type(cls):
|
|
262
|
+
return cls.__retrace_unproxied__ if issubclass(cls, ExtendingProxy) else cls
|
|
263
|
+
|
|
264
|
+
return type(name, tuple(map(unproxy_type, cls.__bases__)), dict(cls.__dict__))
|
|
265
|
+
|
|
266
|
+
def make_extensible(cls, handler, on_new):
|
|
267
|
+
|
|
268
|
+
cls.__retrace_unproxied__ = cls.__base__
|
|
269
|
+
|
|
270
|
+
def init_subclass(*args, **kwargs):
|
|
271
|
+
print(f'In init_subclass: {args} {kwargs}')
|
|
272
|
+
# subclass.__retrace_unproxied__ = create_unproxied_type(subclass)
|
|
273
|
+
|
|
274
|
+
# proxy_method_descriptors(cls = subclass, handler = handler)
|
|
275
|
+
|
|
276
|
+
# if not issubclass(subclass, InternalProxy):
|
|
277
|
+
# cls.__new__ = functional.compose(cls.__new__, functional.side_effect(on_new))
|
|
278
|
+
# cls.__bases__ = cls.__bases__ + (InternalProxy,)
|
|
279
|
+
|
|
280
|
+
cls.__init_subclass__ = init_subclass
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import retracesoftware.functional as functional
|
|
2
|
+
import retracesoftware_utils as utils
|
|
3
|
+
|
|
4
|
+
from retracesoftware.proxy.proxytype import dynamic_proxytype, superdict, is_descriptor, extending_proxytype, dynamic_int_proxytype, make_extensible
|
|
5
|
+
from retracesoftware.proxy.gateway import gateway_pair
|
|
6
|
+
from retracesoftware.proxy.proxysystem import ProxySystem
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
class ExtendedProxy:
|
|
11
|
+
__slots__ = []
|
|
12
|
+
|
|
13
|
+
class ProxyRef:
|
|
14
|
+
def __init__(self, module, name):
|
|
15
|
+
self.module = module
|
|
16
|
+
self.name = name
|
|
17
|
+
|
|
18
|
+
def resolve(self):
|
|
19
|
+
return getattr(sys.modules[self.module], self.name)
|
|
20
|
+
|
|
21
|
+
class ProxySpec(ProxyRef):
|
|
22
|
+
def __init__(self, module, name, methods, members):
|
|
23
|
+
super().__init__(module, name)
|
|
24
|
+
self.methods = methods
|
|
25
|
+
self.members = members
|
|
26
|
+
|
|
27
|
+
def __str__(self):
|
|
28
|
+
return f'ProxySpec(module = {self.module}, name = {self.name}, methods = {self.methods}, members = {self.members})'
|
|
29
|
+
|
|
30
|
+
def keys_where_value(pred, dict):
|
|
31
|
+
for key,value in dict.items():
|
|
32
|
+
if pred(value): yield key
|
|
33
|
+
|
|
34
|
+
def resolveable(obj):
|
|
35
|
+
try:
|
|
36
|
+
return getattr(sys.modules[obj.__module__], obj.__name__) is obj
|
|
37
|
+
except:
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
class ExtProxytype:
|
|
41
|
+
|
|
42
|
+
def __init__(self, gateway, extended_types, writer):
|
|
43
|
+
self.gateway = gateway
|
|
44
|
+
self.writer = writer
|
|
45
|
+
self.extended_types = extended_types
|
|
46
|
+
|
|
47
|
+
def __call__(self, cls):
|
|
48
|
+
assert isinstance(cls, type)
|
|
49
|
+
|
|
50
|
+
if cls in self.extended_types:
|
|
51
|
+
return functional.side_effect(lambda obj: utils.set_type(obj, self.extended_types[cls]))
|
|
52
|
+
else:
|
|
53
|
+
if resolveable(cls):
|
|
54
|
+
ref = self.writer.handle(ProxyRef(name = cls.__name__, module = cls.__module__))
|
|
55
|
+
else:
|
|
56
|
+
blacklist = ['__getattribute__']
|
|
57
|
+
descriptors = {k: v for k,v in superdict(cls).items() if k not in blacklist and is_descriptor(v) }
|
|
58
|
+
|
|
59
|
+
methods = [k for k, v in descriptors.items() if utils.is_method_descriptor(v)]
|
|
60
|
+
members = [k for k, v in descriptors.items() if not utils.is_method_descriptor(v)]
|
|
61
|
+
|
|
62
|
+
ref = self.writer.handle(ProxySpec(name = cls.__name__,
|
|
63
|
+
module = cls.__module__,
|
|
64
|
+
methods = methods,
|
|
65
|
+
members = members))
|
|
66
|
+
|
|
67
|
+
proxytype = dynamic_proxytype(handler = self.gateway, cls = cls)
|
|
68
|
+
|
|
69
|
+
self.writer.type_serializer[proxytype] = functional.constantly(ref)
|
|
70
|
+
return proxytype
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# when
|
|
74
|
+
class RecordProxySystem(ProxySystem):
|
|
75
|
+
|
|
76
|
+
def __init__(self, thread_state, immutable_types, tracer, writer):
|
|
77
|
+
super().__init__(thread_state = thread_state)
|
|
78
|
+
|
|
79
|
+
self.immutable_types = immutable_types
|
|
80
|
+
|
|
81
|
+
self.extended_types = {}
|
|
82
|
+
self.writer = writer
|
|
83
|
+
self.bind = writer.placeholder
|
|
84
|
+
|
|
85
|
+
# on_ext_result = writer.handle('RESULT')
|
|
86
|
+
on_ext_result = functional.if_then_else(
|
|
87
|
+
functional.isinstanceof(str), writer.handle('RESULT'), writer)
|
|
88
|
+
|
|
89
|
+
def int_proxytype(gateway):
|
|
90
|
+
return lambda cls: dynamic_int_proxytype(handler = gateway, cls = cls, bind = self.bind)
|
|
91
|
+
|
|
92
|
+
def ext_proxytype(gateway):
|
|
93
|
+
return ExtProxytype(gateway = gateway, writer = writer, extended_types = self.extended_types)
|
|
94
|
+
|
|
95
|
+
error = writer.handle('ERROR')
|
|
96
|
+
|
|
97
|
+
def write_error(cls, val, traceback):
|
|
98
|
+
error(cls, val)
|
|
99
|
+
|
|
100
|
+
self.ext_handler, self.int_handler = gateway_pair(
|
|
101
|
+
thread_state,
|
|
102
|
+
tracer,
|
|
103
|
+
immutable_types = immutable_types,
|
|
104
|
+
int_proxytype = int_proxytype,
|
|
105
|
+
ext_proxytype = ext_proxytype,
|
|
106
|
+
on_int_call = writer.handle('CALL'),
|
|
107
|
+
on_ext_result = functional.side_effect(on_ext_result),
|
|
108
|
+
on_ext_error = write_error)
|
|
109
|
+
|
|
110
|
+
def extend_type(self, base):
|
|
111
|
+
|
|
112
|
+
if base in self.extended_types:
|
|
113
|
+
return self.extended_types[base]
|
|
114
|
+
|
|
115
|
+
# self.tracer.log('proxy.ext.new.extended', f'{base.__module__}.{base.__name__}')
|
|
116
|
+
|
|
117
|
+
extended = extending_proxytype(
|
|
118
|
+
cls = base,
|
|
119
|
+
thread_state = self.thread_state,
|
|
120
|
+
ext_handler = self.ext_handler,
|
|
121
|
+
int_handler = self.int_handler,
|
|
122
|
+
on_subclass_new = self.bind,
|
|
123
|
+
is_stub = False)
|
|
124
|
+
|
|
125
|
+
ref = self.writer.handle(ProxyRef(name = base.__name__, module = base.__module__,))
|
|
126
|
+
self.writer.type_serializer[extended] = functional.constantly(ref)
|
|
127
|
+
|
|
128
|
+
# make_extensible(cls = extended, handler = self.int_handler, on_new = self.writer.placeholder)
|
|
129
|
+
|
|
130
|
+
self.immutable_types.add(extended)
|
|
131
|
+
self.extended_types[base] = extended
|
|
132
|
+
|
|
133
|
+
return extended
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import retracesoftware.functional as functional
|
|
2
|
+
import retracesoftware_utils as utils
|
|
3
|
+
|
|
4
|
+
from retracesoftware.proxy.proxytype import dynamic_proxytype, dynamic_int_proxytype, extending_proxytype, make_extensible, dynamic_stubtype, stubtype_from_spec, Stub
|
|
5
|
+
from retracesoftware.proxy.gateway import gateway_pair
|
|
6
|
+
|
|
7
|
+
from retracesoftware.proxy.record import ProxyRef, ProxySpec
|
|
8
|
+
from retracesoftware.proxy.proxysystem import ProxySystem
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
# we can have a dummy method descriptor, its has a __name__ and when called, returns the next element
|
|
13
|
+
|
|
14
|
+
# for types, we can patch the __new__ method
|
|
15
|
+
# do it from C and immutable types can be patched too
|
|
16
|
+
# patch the tp_new pointer?
|
|
17
|
+
|
|
18
|
+
class ReplayProxySystem(ProxySystem):
|
|
19
|
+
|
|
20
|
+
def stubtype(self, cls):
|
|
21
|
+
return dynamic_proxytype(handler = self.ext_handler, cls = cls)
|
|
22
|
+
|
|
23
|
+
def stubtype_from_spec(self, spec):
|
|
24
|
+
print (f'FOOO!!! {spec}')
|
|
25
|
+
return stubtype_from_spec(
|
|
26
|
+
handler = self.ext_handler,
|
|
27
|
+
module = spec.module,
|
|
28
|
+
name = spec.name,
|
|
29
|
+
methods = spec.methods,
|
|
30
|
+
members = spec.members)
|
|
31
|
+
|
|
32
|
+
@utils.striptraceback
|
|
33
|
+
def next_result(self):
|
|
34
|
+
while True:
|
|
35
|
+
next = self.reader()
|
|
36
|
+
|
|
37
|
+
if next == 'CALL':
|
|
38
|
+
func = self.reader()
|
|
39
|
+
args = self.reader()
|
|
40
|
+
kwargs = self.reader()
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
func(*args, **kwargs)
|
|
44
|
+
except:
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
elif next == 'RESULT':
|
|
48
|
+
return self.reader()
|
|
49
|
+
elif next == 'ERROR':
|
|
50
|
+
err_type = self.reader()
|
|
51
|
+
err_value = self.reader()
|
|
52
|
+
utils.raise_exception(err_type, err_value)
|
|
53
|
+
else:
|
|
54
|
+
assert not isinstance(next, str)
|
|
55
|
+
return next
|
|
56
|
+
|
|
57
|
+
def __init__(self, thread_state, immutable_types, tracer, reader):
|
|
58
|
+
# self.writer = writer
|
|
59
|
+
super().__init__(thread_state = thread_state)
|
|
60
|
+
self.immutable_types = immutable_types
|
|
61
|
+
self.reader = reader
|
|
62
|
+
self.bind = self.reader.supply
|
|
63
|
+
|
|
64
|
+
add_stubtype = functional.side_effect(immutable_types.add)
|
|
65
|
+
|
|
66
|
+
reader.type_deserializer[ProxyRef] = functional.sequence(lambda ref: ref.resolve(), self.stubtype, add_stubtype)
|
|
67
|
+
reader.type_deserializer[ProxySpec] = functional.sequence(self.stubtype_from_spec, add_stubtype)
|
|
68
|
+
|
|
69
|
+
# on_ext_result = functional.if_then_else(
|
|
70
|
+
# functional.is_instanceof(str), writer.handle('RESULT'), writer)
|
|
71
|
+
|
|
72
|
+
def int_proxytype(gateway):
|
|
73
|
+
return lambda cls: dynamic_int_proxytype(handler = gateway, cls = cls, bind = self.bind)
|
|
74
|
+
|
|
75
|
+
def is_stub_type(obj):
|
|
76
|
+
return functional.typeof(obj) is type and issubclass(obj, Stub)
|
|
77
|
+
|
|
78
|
+
create_stubs = functional.walker(functional.when(is_stub_type, lambda cls: cls()))
|
|
79
|
+
|
|
80
|
+
ext_apply = functional.repeatedly(functional.sequence(self.next_result, create_stubs))
|
|
81
|
+
|
|
82
|
+
self.ext_handler, self.int_handler = gateway_pair(
|
|
83
|
+
thread_state,
|
|
84
|
+
tracer,
|
|
85
|
+
immutable_types = immutable_types,
|
|
86
|
+
ext_apply = ext_apply,
|
|
87
|
+
int_proxytype = int_proxytype,
|
|
88
|
+
ext_proxytype = functional.identity)
|
|
89
|
+
|
|
90
|
+
def extend_type(self, base):
|
|
91
|
+
|
|
92
|
+
# ok, how to provide __getattr__ style access,
|
|
93
|
+
|
|
94
|
+
extended = extending_proxytype(
|
|
95
|
+
cls = base,
|
|
96
|
+
thread_state = self.thread_state,
|
|
97
|
+
int_handler = self.int_handler,
|
|
98
|
+
ext_handler = self.ext_handler,
|
|
99
|
+
on_subclass_new = self.bind,
|
|
100
|
+
is_stub = True)
|
|
101
|
+
|
|
102
|
+
self.immutable_types.add(extended)
|
|
103
|
+
# proxytype = extending_proxytype(base)
|
|
104
|
+
|
|
105
|
+
# make_extensible(cls = extended,
|
|
106
|
+
# int_handler = self.int_handler,
|
|
107
|
+
# ext_handler = self.ext_handler,
|
|
108
|
+
# on_new = self.reader.supply)
|
|
109
|
+
|
|
110
|
+
return extended
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import retracesoftware.functional as functional
|
|
2
|
+
import retracesoftware_utils as utils
|
|
3
|
+
|
|
4
|
+
class ThreadSwitch:
|
|
5
|
+
def __init__(self, thread_id):
|
|
6
|
+
self.thread_id = thread_id
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def thread_aware_writer(writer):
|
|
10
|
+
on_thread_switch = functional.sequence(utils.thread_id(), writer.handle('THREAD_SWITCH'))
|
|
11
|
+
return utils.threadawareproxy(on_thread_switch = on_thread_switch, target = writer)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: retracesoftware_proxy
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Proxy layer for retracesoftware runtime
|
|
5
|
+
License: Apache-2.0
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: retracesoftware_utils
|
|
9
|
+
Requires-Dist: retracesoftware_functional
|
|
10
|
+
Requires-Dist: retracesoftware_stream
|
|
11
|
+
|
|
12
|
+
# proxy
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
retracesoftware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
retracesoftware/config.json,sha256=aedf9CXxOBkcQk3BJVrh0GuBkIAjBGBRlrTXdoRJ-MY,8108
|
|
3
|
+
retracesoftware/install/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
retracesoftware/install/config.py,sha256=EzE5ifQF2lo--hu2njI4T0FJ-zlnWDJV6i7x0DMkVTw,1364
|
|
5
|
+
retracesoftware/install/edgecases.py,sha256=NR3lyvad9sRsyeDv_Ya8V4xMgPsMPOi9rMcnFOJGOEA,6330
|
|
6
|
+
retracesoftware/install/globals.py,sha256=F8XvIoZQQ10gSRalk30dvdKllxlwxkaggYY6FogLDxY,510
|
|
7
|
+
retracesoftware/install/install.py,sha256=VNtivSf6A9wtLzIkZKJQ7thPkYTdjtTmxaIkPUOwLhg,5942
|
|
8
|
+
retracesoftware/install/patcher.py,sha256=5DGzVaNM53Z_KWz-wWQxlr1WqeWuuxKoVZyN5tNGuTw,15866
|
|
9
|
+
retracesoftware/install/predicate.py,sha256=tX7NQc0rGkyyHYO3mduYHcJHbw1wczT53m_Dpkzo6do,2679
|
|
10
|
+
retracesoftware/install/record.py,sha256=mJyz8ZFnrveDCvrUHksTXaFZbBX10yqH6UBV1QH5EwA,4370
|
|
11
|
+
retracesoftware/install/references.py,sha256=0nUY_9BkeFz2imcw97rcJNq2jqISCB8dysBbCrh1eCo,1623
|
|
12
|
+
retracesoftware/install/replay.py,sha256=ox43e8k_uvn9w6vf6rt8f3KwaXcBVx2GbvWaLZpwqR4,4952
|
|
13
|
+
retracesoftware/install/tracer.py,sha256=dFhXKkmvGLF-_WzQvZXxNO1Ftj6crH1SM6pGBU4cqMY,4586
|
|
14
|
+
retracesoftware/install/typeutils.py,sha256=_a1PuwdCsYjG1Nkd77V-flqYtwbD4RkJVKn6Z-xABL4,1813
|
|
15
|
+
retracesoftware/proxy/__init__.py,sha256=NaGsqoj4X3NpHfTAmRIfsXM16R6AGE99ciQeknj3sXc,119
|
|
16
|
+
retracesoftware/proxy/gateway.py,sha256=JtSwwllXiUykpNdojbK7okyYadRnILGgpRCHxAQijZs,3911
|
|
17
|
+
retracesoftware/proxy/proxyfactory.py,sha256=2PgC0NtDbRmhmU--caTiQDsaF8s1h9tavQxvPIow_bM,11912
|
|
18
|
+
retracesoftware/proxy/proxysystem.py,sha256=kDdtea-vCcsqdwSwmgGBBvVrIRl6Gwb89Wgx6VSIwgQ,759
|
|
19
|
+
retracesoftware/proxy/proxytype.py,sha256=P78aL3_aemG8p3NKmP4YfAcwC8IDr7LIq5-dkV4n0Ec,9038
|
|
20
|
+
retracesoftware/proxy/record.py,sha256=yI8CH0oOyrAyvjy9JsawgkQh9jYTlg9sQ_CcejrFKO4,4772
|
|
21
|
+
retracesoftware/proxy/replay.py,sha256=usbb2OTX6uJG_zialqHk9en0mxD2xEhjPajMZDjZnkQ,3940
|
|
22
|
+
retracesoftware/proxy/thread.py,sha256=9_6gWiRbir77f9kelpvXaTWviRfZo0ACkKPdGNbrq2Q,394
|
|
23
|
+
retracesoftware_proxy-0.1.0.dist-info/METADATA,sha256=c24hdDKP-miIrX6mM1yVyXCQeu0ozLP4N0ebtqiGccw,324
|
|
24
|
+
retracesoftware_proxy-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
25
|
+
retracesoftware_proxy-0.1.0.dist-info/top_level.txt,sha256=hYHsR6txLidmqvjBMITpIHvmJJbmoCAgr76-IpZPRz8,16
|
|
26
|
+
retracesoftware_proxy-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
retracesoftware
|