retracesoftware-proxy 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.
- retracesoftware/config.json +7 -0
- retracesoftware/install/install.py +2 -26
- retracesoftware/install/patcher.py +52 -9
- retracesoftware/install/record.py +15 -40
- retracesoftware/install/replay.py +4 -101
- retracesoftware/install/tracer.py +18 -16
- retracesoftware/proxy/__init__.py +1 -1
- retracesoftware/proxy/gateway.py +25 -76
- retracesoftware/proxy/proxyfactory.py +194 -194
- retracesoftware/proxy/proxysystem.py +192 -10
- retracesoftware/proxy/proxytype.py +235 -96
- retracesoftware/proxy/record.py +184 -96
- retracesoftware/proxy/replay.py +184 -60
- retracesoftware/proxy/stubfactory.py +141 -0
- retracesoftware/proxy/thread.py +40 -5
- {retracesoftware_proxy-0.1.0.dist-info → retracesoftware_proxy-0.1.2.dist-info}/METADATA +1 -6
- retracesoftware_proxy-0.1.2.dist-info/RECORD +27 -0
- retracesoftware_proxy-0.1.0.dist-info/RECORD +0 -26
- {retracesoftware_proxy-0.1.0.dist-info → retracesoftware_proxy-0.1.2.dist-info}/WHEEL +0 -0
- {retracesoftware_proxy-0.1.0.dist-info → retracesoftware_proxy-0.1.2.dist-info}/top_level.txt +0 -0
retracesoftware/proxy/record.py
CHANGED
|
@@ -1,133 +1,221 @@
|
|
|
1
1
|
import retracesoftware.functional as functional
|
|
2
|
-
import
|
|
2
|
+
import retracesoftware.utils as utils
|
|
3
|
+
import retracesoftware.stream as stream
|
|
3
4
|
|
|
4
|
-
from retracesoftware.proxy.proxytype import
|
|
5
|
-
from retracesoftware.proxy.gateway import gateway_pair
|
|
5
|
+
from retracesoftware.proxy.proxytype import *
|
|
6
|
+
# from retracesoftware.proxy.gateway import gateway_pair
|
|
6
7
|
from retracesoftware.proxy.proxysystem import ProxySystem
|
|
8
|
+
from retracesoftware.proxy.thread import write_thread_switch
|
|
9
|
+
from retracesoftware.install.tracer import Tracer
|
|
10
|
+
from retracesoftware.proxy.stubfactory import StubRef, ExtendedRef
|
|
7
11
|
|
|
8
12
|
import sys
|
|
13
|
+
import os
|
|
14
|
+
import types
|
|
15
|
+
import gc
|
|
9
16
|
|
|
10
|
-
class
|
|
11
|
-
__slots__ = []
|
|
17
|
+
class Placeholder:
|
|
18
|
+
__slots__ = ['id', '__weakref__']
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
|
|
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})'
|
|
20
|
+
def __init__(self, id):
|
|
21
|
+
self.id = id
|
|
29
22
|
|
|
30
23
|
def keys_where_value(pred, dict):
|
|
31
24
|
for key,value in dict.items():
|
|
32
25
|
if pred(value): yield key
|
|
33
26
|
|
|
27
|
+
types_lookup = {v:k for k,v in types.__dict__.items() if isinstance(v, type)}
|
|
28
|
+
|
|
29
|
+
def resolve(obj):
|
|
30
|
+
try:
|
|
31
|
+
return getattr(sys.modules[obj.__module__], obj.__name__)
|
|
32
|
+
except:
|
|
33
|
+
return None
|
|
34
|
+
|
|
34
35
|
def resolveable(obj):
|
|
35
36
|
try:
|
|
36
37
|
return getattr(sys.modules[obj.__module__], obj.__name__) is obj
|
|
37
38
|
except:
|
|
38
39
|
return False
|
|
40
|
+
|
|
41
|
+
def resolveable_name(obj):
|
|
42
|
+
if obj in types_lookup:
|
|
43
|
+
return ('types', types_lookup[obj])
|
|
44
|
+
elif resolve(obj) is obj:
|
|
45
|
+
return (obj.__module__, obj.__name__)
|
|
46
|
+
else:
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
# when
|
|
50
|
+
class RecordProxySystem(ProxySystem):
|
|
39
51
|
|
|
40
|
-
|
|
52
|
+
def bind(self, obj):
|
|
53
|
+
self.bindings[obj] = self.writer.handle(Placeholder(self.next_placeholder_id))
|
|
54
|
+
self.writer(self.bindings[obj])
|
|
55
|
+
self.next_placeholder_id += 1
|
|
56
|
+
|
|
57
|
+
def before_fork(self):
|
|
58
|
+
self.writer.close()
|
|
59
|
+
super().before_fork()
|
|
60
|
+
# self.writer.path = self.dynamic_path
|
|
61
|
+
|
|
62
|
+
def after_fork_in_child(self):
|
|
63
|
+
new_path = self.new_child_path(self.writer.path)
|
|
64
|
+
new_path.parent.mkdir()
|
|
65
|
+
self.writer.path = new_path
|
|
66
|
+
super().after_fork_in_child()
|
|
67
|
+
|
|
68
|
+
def after_fork_in_parent(self):
|
|
69
|
+
super().after_fork_in_parent()
|
|
70
|
+
self.thread_state.value = self.saved_thread_state
|
|
71
|
+
self.writer.reopen()
|
|
72
|
+
|
|
73
|
+
def __init__(self, thread_state,
|
|
74
|
+
immutable_types,
|
|
75
|
+
tracing_config,
|
|
76
|
+
path):
|
|
77
|
+
|
|
78
|
+
self.fork_counter = 0
|
|
79
|
+
|
|
80
|
+
self.getpid = thread_state.wrap(
|
|
81
|
+
desired_state = 'disabled', function = os.getpid)
|
|
82
|
+
|
|
83
|
+
self.pid = self.getpid()
|
|
41
84
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
85
|
+
self.writer = stream.writer(path)
|
|
86
|
+
|
|
87
|
+
w = self.writer.handle('TRACE')
|
|
88
|
+
def trace_writer(*args):
|
|
89
|
+
print(f'Trace: {args}')
|
|
90
|
+
w(*args)
|
|
46
91
|
|
|
47
|
-
|
|
48
|
-
|
|
92
|
+
self.extended_types = {}
|
|
93
|
+
self.bindings = utils.id_dict()
|
|
94
|
+
self.next_placeholder_id = 0
|
|
49
95
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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))
|
|
96
|
+
serialize = functional.walker(self.bindings.get_else_key)
|
|
97
|
+
|
|
98
|
+
thread_switch_monitor = \
|
|
99
|
+
utils.thread_switch_monitor(
|
|
100
|
+
functional.repeatedly(functional.sequence(utils.thread_id, self.writer)))
|
|
101
|
+
|
|
102
|
+
self.sync = lambda function: functional.firstof(thread_switch_monitor, functional.always(self.writer.handle('SYNC')), function)
|
|
66
103
|
|
|
67
|
-
|
|
104
|
+
error = self.writer.handle('ERROR')
|
|
68
105
|
|
|
69
|
-
|
|
70
|
-
|
|
106
|
+
def write_error(cls, val, traceback):
|
|
107
|
+
error(cls, val)
|
|
71
108
|
|
|
109
|
+
self.set_thread_id = functional.partial(utils.set_thread_id, self.writer)
|
|
72
110
|
|
|
73
|
-
|
|
74
|
-
class RecordProxySystem(ProxySystem):
|
|
75
|
-
|
|
76
|
-
def __init__(self, thread_state, immutable_types, tracer, writer):
|
|
77
|
-
super().__init__(thread_state = thread_state)
|
|
111
|
+
def watch(f): return functional.either(thread_switch_monitor, f)
|
|
78
112
|
|
|
79
|
-
|
|
113
|
+
tracer = Tracer(tracing_config, writer = trace_writer)
|
|
80
114
|
|
|
81
|
-
self.
|
|
82
|
-
|
|
83
|
-
self.
|
|
115
|
+
self.wrap_int_to_ext = watch
|
|
116
|
+
|
|
117
|
+
self.on_int_call = functional.mapargs(transform = serialize, function = self.writer.handle('CALL'))
|
|
118
|
+
|
|
119
|
+
self.on_ext_result = functional.if_then_else(
|
|
120
|
+
functional.isinstanceof(str),
|
|
121
|
+
self.writer.handle('RESULT'),
|
|
122
|
+
functional.sequence(serialize, self.writer))
|
|
123
|
+
|
|
124
|
+
self.on_ext_error = write_error
|
|
84
125
|
|
|
85
|
-
|
|
86
|
-
on_ext_result = functional.if_then_else(
|
|
87
|
-
functional.isinstanceof(str), writer.handle('RESULT'), writer)
|
|
126
|
+
self.ext_apply = self.int_apply = functional.apply
|
|
88
127
|
|
|
89
|
-
|
|
90
|
-
|
|
128
|
+
super().__init__(thread_state = thread_state, tracer = tracer, immutable_types = immutable_types)
|
|
129
|
+
|
|
130
|
+
def dynamic_ext_proxytype(self, cls):
|
|
91
131
|
|
|
92
|
-
|
|
93
|
-
return ExtProxytype(gateway = gateway, writer = writer, extended_types = self.extended_types)
|
|
94
|
-
|
|
95
|
-
error = writer.handle('ERROR')
|
|
132
|
+
proxytype = super().dynamic_ext_proxytype(cls)
|
|
96
133
|
|
|
97
|
-
|
|
98
|
-
error(cls, val)
|
|
134
|
+
blacklist = ['__class__', '__dict__', '__module__', '__doc__']
|
|
99
135
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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)
|
|
136
|
+
methods = []
|
|
137
|
+
members = []
|
|
138
|
+
|
|
139
|
+
for key,value in proxytype.__dict__.items():
|
|
140
|
+
if key not in blacklist:
|
|
141
|
+
if utils.is_method_descriptor(value):
|
|
142
|
+
methods.append(key)
|
|
143
|
+
elif not key.startswith("__retrace"):
|
|
144
|
+
members.append(key)
|
|
145
|
+
|
|
146
|
+
ref = self.writer.handle(StubRef(
|
|
147
|
+
name = cls.__name__,
|
|
148
|
+
module = cls.__module__,
|
|
149
|
+
methods = methods,
|
|
150
|
+
members = members))
|
|
124
151
|
|
|
125
|
-
|
|
126
|
-
|
|
152
|
+
# list(proxytype.__dict__.keys())
|
|
153
|
+
|
|
154
|
+
# if resolveable_name(cls):
|
|
155
|
+
# module, name = resolveable_name(cls)
|
|
156
|
+
# ref = self.writer.handle(StubRef(type = 'dynamic', name = name, module = module))
|
|
157
|
+
# else:
|
|
158
|
+
# blacklist = ['__getattribute__']
|
|
159
|
+
# descriptors = {k: v for k,v in superdict(cls).items() if k not in blacklist and is_descriptor(v) }
|
|
160
|
+
|
|
161
|
+
# methods = [k for k, v in descriptors.items() if utils.is_method_descriptor(v)]
|
|
162
|
+
# members = [k for k, v in descriptors.items() if not utils.is_method_descriptor(v)]
|
|
163
|
+
|
|
164
|
+
# ref = self.writer.handle(ProxySpec(name = cls.__name__,
|
|
165
|
+
# module = cls.__module__,
|
|
166
|
+
# methods = methods,
|
|
167
|
+
# members = members))
|
|
168
|
+
|
|
169
|
+
self.writer.type_serializer[proxytype] = functional.constantly(ref)
|
|
170
|
+
|
|
171
|
+
return proxytype
|
|
172
|
+
|
|
173
|
+
def ext_proxytype(self, cls):
|
|
174
|
+
assert isinstance(cls, type), f"record.proxytype requires a type but was passed: {cls}"
|
|
175
|
+
|
|
176
|
+
# resolved = resolve(cls)
|
|
177
|
+
|
|
178
|
+
proxytype = super().ext_proxytype(cls)
|
|
179
|
+
|
|
180
|
+
assert resolve(cls) is cls
|
|
181
|
+
|
|
182
|
+
# ref = self.writer.handle(StubRef(name = cls.__name__,
|
|
183
|
+
# module = cls.__module__))
|
|
184
|
+
|
|
185
|
+
# if resolveable_name(cls):
|
|
186
|
+
# module, name = resolveable_name(cls)
|
|
187
|
+
# ref = self.writer.handle(StubRef(name = cls.__name__, module = cls.__module__))
|
|
188
|
+
# else:
|
|
189
|
+
# blacklist = ['__getattribute__']
|
|
190
|
+
# descriptors = {k: v for k,v in superdict(cls).items() if k not in blacklist and is_descriptor(v) }
|
|
191
|
+
|
|
192
|
+
# methods = [k for k, v in descriptors.items() if utils.is_method_descriptor(v)]
|
|
193
|
+
# members = [k for k, v in descriptors.items() if not utils.is_method_descriptor(v)]
|
|
194
|
+
|
|
195
|
+
# ref = self.writer.handle(ProxySpec(name = cls.__name__,
|
|
196
|
+
# module = cls.__module__,
|
|
197
|
+
# methods = methods,
|
|
198
|
+
# members = members))
|
|
199
|
+
|
|
200
|
+
# self.writer.type_serializer[proxytype] = functional.constantly(ref)
|
|
201
|
+
return proxytype
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def extend_type(self, cls):
|
|
205
|
+
|
|
206
|
+
if cls in self.extended_types:
|
|
207
|
+
return self.extended_types[cls]
|
|
208
|
+
|
|
209
|
+
extended = super().extend_type(cls)
|
|
127
210
|
|
|
128
|
-
|
|
211
|
+
self.extended_types[cls] = extended
|
|
129
212
|
|
|
130
|
-
self.
|
|
131
|
-
|
|
213
|
+
ref = self.writer.handle(ExtendedRef(name = cls.__name__,
|
|
214
|
+
module = cls.__module__))
|
|
215
|
+
|
|
216
|
+
# for binding?
|
|
217
|
+
# self.writer(ref)
|
|
218
|
+
|
|
219
|
+
self.writer.type_serializer[extended] = functional.constantly(ref)
|
|
132
220
|
|
|
133
221
|
return extended
|
retracesoftware/proxy/replay.py
CHANGED
|
@@ -1,43 +1,55 @@
|
|
|
1
1
|
import retracesoftware.functional as functional
|
|
2
2
|
import retracesoftware_utils as utils
|
|
3
|
+
import retracesoftware.stream as stream
|
|
3
4
|
|
|
4
|
-
from retracesoftware.
|
|
5
|
-
from retracesoftware.proxy.
|
|
6
|
-
|
|
7
|
-
from retracesoftware.proxy.
|
|
8
|
-
from retracesoftware.proxy.
|
|
5
|
+
from retracesoftware.install.tracer import Tracer
|
|
6
|
+
from retracesoftware.proxy.thread import per_thread_messages
|
|
7
|
+
from retracesoftware.proxy.proxytype import *
|
|
8
|
+
# from retracesoftware.proxy.gateway import gateway_pair
|
|
9
|
+
from retracesoftware.proxy.record import StubRef, Placeholder
|
|
10
|
+
from retracesoftware.proxy.proxysystem import ProxySystem, RetraceError
|
|
11
|
+
from retracesoftware.proxy.stubfactory import StubFactory, StubFunction
|
|
9
12
|
|
|
10
13
|
import os
|
|
11
|
-
|
|
14
|
+
import weakref
|
|
15
|
+
import traceback
|
|
12
16
|
# we can have a dummy method descriptor, its has a __name__ and when called, returns the next element
|
|
13
17
|
|
|
14
18
|
# for types, we can patch the __new__ method
|
|
15
19
|
# do it from C and immutable types can be patched too
|
|
16
20
|
# patch the tp_new pointer?
|
|
17
21
|
|
|
22
|
+
class ReplayError(RetraceError):
|
|
23
|
+
pass
|
|
24
|
+
|
|
18
25
|
class ReplayProxySystem(ProxySystem):
|
|
19
26
|
|
|
20
27
|
def stubtype(self, cls):
|
|
28
|
+
print(f'In stubtype, class: {cls}')
|
|
29
|
+
assert not issubclass(cls, Proxy)
|
|
30
|
+
|
|
21
31
|
return dynamic_proxytype(handler = self.ext_handler, cls = cls)
|
|
22
32
|
|
|
23
|
-
def
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
def create_stub(self): return True
|
|
34
|
+
|
|
35
|
+
# def stubtype_from_spec(self, spec):
|
|
36
|
+
# print (f'FOOO!!! {spec}')
|
|
37
|
+
# return stubtype_from_spec(
|
|
38
|
+
# handler = self.ext_handler,
|
|
39
|
+
# module = spec.module,
|
|
40
|
+
# name = spec.name,
|
|
41
|
+
# methods = spec.methods,
|
|
42
|
+
# members = spec.members)
|
|
31
43
|
|
|
32
44
|
@utils.striptraceback
|
|
33
45
|
def next_result(self):
|
|
34
46
|
while True:
|
|
35
|
-
next = self.
|
|
47
|
+
next = self.messages()
|
|
36
48
|
|
|
37
49
|
if next == 'CALL':
|
|
38
|
-
func = self.
|
|
39
|
-
args = self.
|
|
40
|
-
kwargs = self.
|
|
50
|
+
func = self.messages()
|
|
51
|
+
args = self.messages()
|
|
52
|
+
kwargs = self.messages()
|
|
41
53
|
|
|
42
54
|
try:
|
|
43
55
|
func(*args, **kwargs)
|
|
@@ -45,66 +57,178 @@ class ReplayProxySystem(ProxySystem):
|
|
|
45
57
|
pass
|
|
46
58
|
|
|
47
59
|
elif next == 'RESULT':
|
|
48
|
-
return self.
|
|
60
|
+
return self.messages()
|
|
49
61
|
elif next == 'ERROR':
|
|
50
|
-
err_type = self.
|
|
51
|
-
err_value = self.
|
|
62
|
+
err_type = self.messages()
|
|
63
|
+
err_value = self.messages()
|
|
52
64
|
utils.raise_exception(err_type, err_value)
|
|
53
65
|
else:
|
|
54
|
-
|
|
66
|
+
if type(next) is str: print('FOOBAR!!!!')
|
|
67
|
+
assert type(next) is not str
|
|
55
68
|
return next
|
|
56
69
|
|
|
57
|
-
def
|
|
70
|
+
def bind(self, obj):
|
|
71
|
+
read = self.messages()
|
|
72
|
+
|
|
73
|
+
assert isinstance(read, Placeholder)
|
|
74
|
+
|
|
75
|
+
self.bindings[read] = obj
|
|
76
|
+
|
|
77
|
+
# def dynamic_path(self):
|
|
78
|
+
# if self.getpid() != self.pid:
|
|
79
|
+
# self.pid = self.getpid()
|
|
80
|
+
# # ok we are in child, calculate new path
|
|
81
|
+
# self.path = self.path / f'fork-{self.fork_counter}'
|
|
82
|
+
# self.fork_counter = 0
|
|
83
|
+
|
|
84
|
+
# return self.path
|
|
85
|
+
|
|
86
|
+
def after_fork_in_child(self):
|
|
87
|
+
self.reader.path = self.new_child_path(self.reader.path)
|
|
88
|
+
super().after_fork_in_child()
|
|
89
|
+
|
|
90
|
+
# def dynamic_ext_proxytype(self, cls):
|
|
91
|
+
# raise Exception('dynamic_ext_proxytype should not be called in replay')
|
|
92
|
+
|
|
93
|
+
def proxy_function(self, obj):
|
|
94
|
+
func = functional.repeatedly(self.next_result)
|
|
95
|
+
func.__name__ = obj.__name__
|
|
96
|
+
|
|
97
|
+
return super().proxy_function(func)
|
|
98
|
+
|
|
99
|
+
def __init__(self,
|
|
100
|
+
thread_state,
|
|
101
|
+
immutable_types,
|
|
102
|
+
tracing_config,
|
|
103
|
+
path,
|
|
104
|
+
fork_path = []):
|
|
105
|
+
|
|
58
106
|
# self.writer = writer
|
|
59
|
-
super().__init__(thread_state = thread_state)
|
|
60
|
-
|
|
107
|
+
# super().__init__(thread_state = thread_state)
|
|
108
|
+
reader = stream.reader(path)
|
|
109
|
+
|
|
110
|
+
self.bindings = utils.id_dict()
|
|
111
|
+
self.set_thread_id = utils.set_thread_id
|
|
112
|
+
self.fork_path = fork_path
|
|
113
|
+
deserialize = functional.walker(self.bindings.get_else_key)
|
|
114
|
+
|
|
115
|
+
self.messages = functional.sequence(per_thread_messages(reader), deserialize)
|
|
116
|
+
|
|
117
|
+
self.stub_factory = StubFactory(thread_state = thread_state, next_result = self.next_result)
|
|
118
|
+
|
|
119
|
+
# messages = reader
|
|
120
|
+
|
|
121
|
+
def readnext():
|
|
122
|
+
with thread_state.select('disabled'):
|
|
123
|
+
try:
|
|
124
|
+
return self.messages()
|
|
125
|
+
except Exception as error:
|
|
126
|
+
# print(f'Error reading stream: {error}')
|
|
127
|
+
traceback.print_exc()
|
|
128
|
+
|
|
129
|
+
os._exit(1)
|
|
130
|
+
|
|
131
|
+
# print(f'read: {obj}')
|
|
132
|
+
# return obj
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# lookup = weakref.WeakKeyDictionary()
|
|
136
|
+
|
|
137
|
+
# debug = debug_level(config)
|
|
138
|
+
|
|
139
|
+
# int_refs = {}
|
|
140
|
+
|
|
141
|
+
def read_required(required):
|
|
142
|
+
obj = readnext()
|
|
143
|
+
if obj != required:
|
|
144
|
+
print(f'Replay: {required} Record: {obj}')
|
|
145
|
+
for i in range(5):
|
|
146
|
+
print(readnext())
|
|
147
|
+
|
|
148
|
+
utils.sigtrap(None)
|
|
149
|
+
os._exit(1)
|
|
150
|
+
raise Exception(f'Expected: {required} but got: {obj}')
|
|
151
|
+
|
|
152
|
+
def trace_writer(name, *args):
|
|
153
|
+
with thread_state.select('disabled'):
|
|
154
|
+
print(f'Trace: {name} {args}')
|
|
155
|
+
|
|
156
|
+
read_required('TRACE')
|
|
157
|
+
read_required(name)
|
|
158
|
+
|
|
159
|
+
for arg in args:
|
|
160
|
+
read_required(arg)
|
|
161
|
+
|
|
162
|
+
# self.tracer = Tracer(tracing_config, writer = trace_writer)
|
|
163
|
+
# self.immutable_types = immutable_types
|
|
164
|
+
|
|
61
165
|
self.reader = reader
|
|
62
|
-
self.bind = self.reader.supply
|
|
63
166
|
|
|
64
|
-
|
|
167
|
+
# def foo(cls):
|
|
168
|
+
# print(cls)
|
|
169
|
+
# assert isinstance(cls, type)
|
|
170
|
+
# immutable_types.add(cls)
|
|
171
|
+
|
|
172
|
+
# add_stubtype = functional.side_effect(foo)
|
|
173
|
+
# add_stubtype = functional.side_effect(immutable_types.add)
|
|
174
|
+
|
|
175
|
+
# reader.type_deserializer[ProxyRef] = functional.sequence(lambda ref: ref.resolve(), self.stubtype, add_stubtype)
|
|
65
176
|
|
|
66
|
-
reader.type_deserializer[
|
|
67
|
-
reader.type_deserializer[ProxySpec] = functional.sequence(self.stubtype_from_spec, add_stubtype)
|
|
177
|
+
reader.type_deserializer[StubRef] = self.stub_factory
|
|
178
|
+
# reader.type_deserializer[ProxySpec] = functional.sequence(self.stubtype_from_spec, add_stubtype)
|
|
68
179
|
|
|
69
180
|
# on_ext_result = functional.if_then_else(
|
|
70
181
|
# functional.is_instanceof(str), writer.handle('RESULT'), writer)
|
|
71
182
|
|
|
72
|
-
def int_proxytype(gateway):
|
|
73
|
-
|
|
183
|
+
# def int_proxytype(gateway):
|
|
184
|
+
# return lambda cls: dynamic_int_proxytype(handler = gateway, cls = cls, bind = self.bind)
|
|
74
185
|
|
|
75
|
-
|
|
76
|
-
|
|
186
|
+
# create_stubs = functional.walker(functional.when(is_stub_ref, lambda stub: stub.create()))
|
|
187
|
+
# create_stubs = functional.walker(functional.when(is_stub_type, lambda cls: cls()))
|
|
77
188
|
|
|
78
|
-
|
|
189
|
+
# self.ext_apply = functional.repeatedly(functional.sequence(self.next_result, create_stubs))
|
|
190
|
+
# self.ext_apply = functional.repeatedly(self.next_result)
|
|
191
|
+
|
|
192
|
+
def read_sync(): read_required('SYNC')
|
|
79
193
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
194
|
+
self.sync = lambda function: utils.observer(on_call = functional.always(read_sync), function = function)
|
|
195
|
+
|
|
196
|
+
super().__init__(thread_state = thread_state,
|
|
197
|
+
tracer = Tracer(tracing_config, writer = trace_writer),
|
|
198
|
+
immutable_types = immutable_types)
|
|
199
|
+
|
|
200
|
+
# super().__init__(
|
|
201
|
+
# thread_state=thread_state,
|
|
202
|
+
# immutable_types= immutable_types,
|
|
203
|
+
# tracer=self.tracer,
|
|
204
|
+
# ext_apply = ext_apply)
|
|
205
|
+
|
|
206
|
+
# self.ext_handler, self.int_handler = gateway_pair(
|
|
207
|
+
# thread_state,
|
|
208
|
+
# self.tracer,
|
|
209
|
+
# immutable_types = immutable_types,
|
|
210
|
+
# ext_apply = ext_apply,
|
|
211
|
+
# int_proxytype = int_proxytype,
|
|
212
|
+
# ext_proxytype = functional.identity)
|
|
213
|
+
|
|
214
|
+
# def extend_type(self, base):
|
|
91
215
|
|
|
92
|
-
|
|
216
|
+
# # ok, how to provide __getattr__ style access,
|
|
93
217
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
218
|
+
# extended = extending_proxytype(
|
|
219
|
+
# cls = base,
|
|
220
|
+
# thread_state = self.thread_state,
|
|
221
|
+
# int_handler = self.int_handler,
|
|
222
|
+
# ext_handler = self.ext_handler,
|
|
223
|
+
# on_subclass_new = self.bind,
|
|
224
|
+
# is_stub = True)
|
|
101
225
|
|
|
102
|
-
|
|
103
|
-
|
|
226
|
+
# self.immutable_types.add(extended)
|
|
227
|
+
# # proxytype = extending_proxytype(base)
|
|
104
228
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
229
|
+
# # make_extensible(cls = extended,
|
|
230
|
+
# # int_handler = self.int_handler,
|
|
231
|
+
# # ext_handler = self.ext_handler,
|
|
232
|
+
# # on_new = self.reader.supply)
|
|
109
233
|
|
|
110
|
-
|
|
234
|
+
# return extended
|