retracesoftware-proxy 0.1.0__py3-none-any.whl → 0.1.1__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 +31 -7
- retracesoftware/install/record.py +9 -41
- retracesoftware/install/replay.py +4 -101
- retracesoftware/install/tracer.py +2 -2
- retracesoftware/proxy/__init__.py +1 -1
- retracesoftware/proxy/gateway.py +129 -71
- retracesoftware/proxy/proxysystem.py +169 -8
- retracesoftware/proxy/proxytype.py +24 -13
- retracesoftware/proxy/record.py +164 -73
- retracesoftware/proxy/replay.py +143 -43
- retracesoftware/proxy/thread.py +40 -5
- {retracesoftware_proxy-0.1.0.dist-info → retracesoftware_proxy-0.1.1.dist-info}/METADATA +1 -6
- retracesoftware_proxy-0.1.1.dist-info/RECORD +26 -0
- retracesoftware_proxy-0.1.0.dist-info/RECORD +0 -26
- {retracesoftware_proxy-0.1.0.dist-info → retracesoftware_proxy-0.1.1.dist-info}/WHEEL +0 -0
- {retracesoftware_proxy-0.1.0.dist-info → retracesoftware_proxy-0.1.1.dist-info}/top_level.txt +0 -0
|
@@ -1,20 +1,181 @@
|
|
|
1
1
|
import retracesoftware.functional as functional
|
|
2
2
|
import retracesoftware_utils as utils
|
|
3
|
-
|
|
4
|
-
from retracesoftware.proxy.
|
|
3
|
+
import types
|
|
4
|
+
from retracesoftware.proxy.gateway import adapter_pair1
|
|
5
|
+
from types import SimpleNamespace
|
|
6
|
+
from retracesoftware.proxy.proxytype import ExtendingProxy
|
|
7
|
+
|
|
8
|
+
from retracesoftware.proxy.proxytype import extending_proxytype, make_extensible, dynamic_proxytype, dynamic_int_proxytype, instantiable_dynamic_proxytype
|
|
9
|
+
|
|
10
|
+
def proxy(proxytype):
|
|
11
|
+
def set_type(cls, obj):
|
|
12
|
+
obj.__class__ = cls
|
|
13
|
+
return obj
|
|
14
|
+
|
|
15
|
+
def can_set_type(cls, obj): return issubclass(cls, ExtendingProxy)
|
|
16
|
+
|
|
17
|
+
create = functional.if_then_else(can_set_type, set_type, utils.create_wrapped)
|
|
18
|
+
|
|
19
|
+
return functional.spread(
|
|
20
|
+
create,
|
|
21
|
+
functional.sequence(functional.typeof, proxytype),
|
|
22
|
+
None)
|
|
23
|
+
|
|
24
|
+
def maybe_proxy(proxytype):
|
|
25
|
+
return functional.if_then_else(
|
|
26
|
+
functional.isinstanceof(utils.Wrapped),
|
|
27
|
+
utils.unwrap,
|
|
28
|
+
proxy(functional.memoize_one_arg(proxytype)))
|
|
29
|
+
|
|
30
|
+
unproxy_execute = functional.mapargs(starting = 1,
|
|
31
|
+
transform = functional.walker(utils.try_unwrap),
|
|
32
|
+
function = functional.apply)
|
|
5
33
|
|
|
6
34
|
class ProxySystem:
|
|
7
35
|
|
|
8
|
-
def
|
|
36
|
+
def wrap_int_to_ext(self, obj): return obj
|
|
37
|
+
def wrap_ext_to_int(self, obj): return obj
|
|
38
|
+
|
|
39
|
+
def on_int_call(self, func, *args, **kwargs):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
def on_ext_result(self, result):
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
def on_ext_error(self, err_type, err_value, err_traceback):
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
def ext_apply(self, func, *args, **kwargs):
|
|
49
|
+
return func(*args, **kwargs)
|
|
50
|
+
|
|
51
|
+
def int_apply(self, func, *args, **kwargs):
|
|
52
|
+
return func(*args, **kwargs)
|
|
53
|
+
|
|
54
|
+
def __init__(self, thread_state, immutable_types, tracer):
|
|
55
|
+
|
|
9
56
|
self.thread_state = thread_state
|
|
57
|
+
self.fork_counter = 0
|
|
58
|
+
self.tracer = tracer
|
|
59
|
+
self.immutable_types = immutable_types
|
|
60
|
+
|
|
61
|
+
def is_immutable_type(cls):
|
|
62
|
+
return issubclass(cls, tuple(immutable_types))
|
|
63
|
+
|
|
64
|
+
is_immutable = functional.sequence(functional.typeof, functional.memoize_one_arg(is_immutable_type))
|
|
65
|
+
|
|
66
|
+
def proxyfactory(proxytype):
|
|
67
|
+
return functional.walker(functional.when_not(is_immutable, maybe_proxy(proxytype)))
|
|
68
|
+
|
|
69
|
+
int_spec = SimpleNamespace(
|
|
70
|
+
proxytype = self.int_proxytype,
|
|
71
|
+
proxy = proxyfactory(self.int_proxytype),
|
|
72
|
+
on_call = tracer('proxy.int.call', self.on_int_call),
|
|
73
|
+
on_result = tracer('proxy.int.result'),
|
|
74
|
+
on_error = tracer('proxy.int.error'),
|
|
75
|
+
apply = self.int_apply,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
ext_spec = SimpleNamespace(
|
|
79
|
+
proxytype = self.ext_proxytype,
|
|
80
|
+
proxy = proxyfactory(self.ext_proxytype),
|
|
81
|
+
on_call = tracer('proxy.ext.call'),
|
|
82
|
+
on_result = self.on_ext_result,
|
|
83
|
+
on_error = self.on_ext_error,
|
|
84
|
+
apply = self.ext_apply
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
int2ext, ext2int = adapter_pair1(int_spec, ext_spec)
|
|
88
|
+
|
|
89
|
+
# self.ext_handler = thread_state.dispatch(default, internal = internal, external = external)
|
|
90
|
+
|
|
91
|
+
def gateway(name, internal = functional.apply, external = functional.apply):
|
|
92
|
+
default = tracer(name, unproxy_execute)
|
|
93
|
+
return thread_state.dispatch(default, internal = internal, external = external)
|
|
94
|
+
|
|
95
|
+
self.ext_handler = gateway('proxy.int.disabled.event', internal = self.wrap_int_to_ext(int2ext))
|
|
96
|
+
self.int_handler = gateway('proxy.ext.disabled.event', external = self.wrap_ext_to_int(ext2int))
|
|
97
|
+
|
|
98
|
+
# return (gateway('proxy.int.disabled.event', internal = wrap_int_to_ext(int_to_ext)),
|
|
99
|
+
# gateway('proxy.ext.disabled.event',
|
|
100
|
+
# external = tracer('proxy.ext_to_int.wrap', ext_to_int)))
|
|
101
|
+
|
|
102
|
+
# # def adapter_pair1(int, ext):
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# self.ext_handler, self.int_handler = gateway_pair(
|
|
106
|
+
# thread_state,
|
|
107
|
+
# self.tracer,
|
|
108
|
+
# immutable_types = immutable_types,
|
|
109
|
+
# wrap_int_to_ext = wrap_int_to_ext,
|
|
110
|
+
# int_proxytype = self.int_proxytype,
|
|
111
|
+
# ext_proxytype = self.ext_proxytype,
|
|
112
|
+
# ext_apply = ext_apply,
|
|
113
|
+
# on_int_call = on_int_call,
|
|
114
|
+
# on_ext_result = on_ext_result,
|
|
115
|
+
# on_ext_error = on_ext_error)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def new_child_path(self, path):
|
|
119
|
+
return path.parent / f'fork-{self.fork_counter}' / path.name
|
|
120
|
+
|
|
121
|
+
def before_fork(self):
|
|
122
|
+
self.saved_thread_state = self.thread_state.value
|
|
123
|
+
self.thread_state.value = 'disabled'
|
|
124
|
+
|
|
125
|
+
def after_fork_in_child(self):
|
|
126
|
+
self.thread_state.value = self.saved_thread_state
|
|
127
|
+
self.fork_counter = 0
|
|
128
|
+
|
|
129
|
+
def after_fork_in_parent(self):
|
|
130
|
+
self.thread_state.value = self.saved_thread_state
|
|
131
|
+
self.fork_counter += 1
|
|
132
|
+
|
|
133
|
+
def create_stub(self): return False
|
|
134
|
+
|
|
135
|
+
def int_proxytype(self, cls):
|
|
136
|
+
return dynamic_int_proxytype(
|
|
137
|
+
handler = self.int_handler,
|
|
138
|
+
cls = cls,
|
|
139
|
+
bind = self.bind)
|
|
140
|
+
|
|
141
|
+
def ext_proxytype(self, cls):
|
|
142
|
+
assert isinstance(cls, type)
|
|
143
|
+
if utils.is_extendable(cls):
|
|
144
|
+
return self.extend_type(cls)
|
|
145
|
+
else:
|
|
146
|
+
return instantiable_dynamic_proxytype(
|
|
147
|
+
handler = self.ext_handler,
|
|
148
|
+
cls = cls,
|
|
149
|
+
thread_state = self.thread_state,
|
|
150
|
+
create_stub = self.create_stub())
|
|
151
|
+
|
|
152
|
+
def extend_type(self, base):
|
|
153
|
+
|
|
154
|
+
extended = extending_proxytype(
|
|
155
|
+
cls = base,
|
|
156
|
+
thread_state = self.thread_state,
|
|
157
|
+
ext_handler = self.ext_handler,
|
|
158
|
+
int_handler = self.int_handler,
|
|
159
|
+
on_subclass_new = self.bind,
|
|
160
|
+
is_stub = self.create_stub())
|
|
161
|
+
|
|
162
|
+
self.immutable_types.add(extended)
|
|
163
|
+
|
|
164
|
+
return extended
|
|
10
165
|
|
|
11
166
|
def __call__(self, obj):
|
|
12
167
|
assert not isinstance(obj, BaseException)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
168
|
+
assert not isinstance(obj, utils.wrapped_function)
|
|
169
|
+
|
|
170
|
+
if type(obj) == type:
|
|
171
|
+
return self.ext_proxytype(obj)
|
|
172
|
+
|
|
173
|
+
elif type(obj) == types.BuiltinFunctionType:
|
|
17
174
|
return utils.wrapped_function(handler = self.ext_handler, target = obj)
|
|
175
|
+
|
|
18
176
|
else:
|
|
19
|
-
|
|
177
|
+
proxytype = dynamic_proxytype(handler = self.ext_handler, cls = type(obj))
|
|
178
|
+
|
|
179
|
+
return utils.create_wrapped(proxytype, obj)
|
|
180
|
+
# raise Exception(f'object {obj} was not proxied as its not a extensible type and is not callable')
|
|
20
181
|
|
|
@@ -112,7 +112,7 @@ def dynamic_proxytype(handler, cls):
|
|
|
112
112
|
|
|
113
113
|
assert not issubclass(cls, BaseException)
|
|
114
114
|
|
|
115
|
-
blacklist = ['__getattribute__', '__hash__', '__del__', '
|
|
115
|
+
blacklist = ['__getattribute__', '__hash__', '__del__', '__call__']
|
|
116
116
|
|
|
117
117
|
to_proxy = [m for m in methods(cls) if m not in blacklist]
|
|
118
118
|
|
|
@@ -128,13 +128,32 @@ def dynamic_proxytype(handler, cls):
|
|
|
128
128
|
|
|
129
129
|
spec['__retrace_target_class__'] = cls
|
|
130
130
|
|
|
131
|
-
target_type = functional.
|
|
131
|
+
target_type = functional.sequence(utils.unwrap, functional.typeof)
|
|
132
132
|
spec['__class__'] = property(target_type)
|
|
133
|
-
|
|
133
|
+
|
|
134
134
|
name = f'retrace.proxied.{cls.__module__}.{cls.__name__}'
|
|
135
135
|
|
|
136
136
|
return type(name, (utils.Wrapped, DynamicProxy), spec)
|
|
137
137
|
|
|
138
|
+
def instantiable_dynamic_proxytype(handler, cls, thread_state, create_stub = False):
|
|
139
|
+
|
|
140
|
+
proxytype = dynamic_proxytype(handler = handler, cls = cls)
|
|
141
|
+
|
|
142
|
+
def create_original(proxytype, *args, **kwargs):
|
|
143
|
+
instance = cls(*args, **kwargs)
|
|
144
|
+
instance.__init__(*args, **kwargs)
|
|
145
|
+
return instance
|
|
146
|
+
|
|
147
|
+
def __new__(proxytype, *args, **kwargs):
|
|
148
|
+
print(f'instantiable_dynamic_proxytype: {cls}')
|
|
149
|
+
|
|
150
|
+
instance = utils.create_stub_object(cls) if create_stub else cls(*args, **kwargs)
|
|
151
|
+
return utils.create_wrapped(proxytype, instance)
|
|
152
|
+
|
|
153
|
+
proxytype.__new__ = thread_state.dispatch(create_original, internal = __new__)
|
|
154
|
+
|
|
155
|
+
return proxytype
|
|
156
|
+
|
|
138
157
|
def dynamic_int_proxytype(handler, cls, bind):
|
|
139
158
|
proxytype = dynamic_proxytype(handler = handler, cls = cls)
|
|
140
159
|
proxytype.__new__ = functional.sequence(proxytype.__new__, functional.side_effect(bind))
|
|
@@ -163,7 +182,7 @@ class DescriptorProxy:
|
|
|
163
182
|
return self.handler(deleter, self.name)
|
|
164
183
|
|
|
165
184
|
|
|
166
|
-
blacklist = ['__getattribute__', '__hash__', '__del__']
|
|
185
|
+
blacklist = ['__getattribute__', '__hash__', '__del__', '__dict__']
|
|
167
186
|
|
|
168
187
|
# if the type can be patched, thats better, all new instances must be of correct type
|
|
169
188
|
|
|
@@ -178,7 +197,7 @@ def extending_proxytype(cls, thread_state, ext_handler, int_handler, on_subclass
|
|
|
178
197
|
proxy_method_descriptors(cls = subclass, handler = int_handler)
|
|
179
198
|
|
|
180
199
|
if not issubclass(subclass, InternalProxy):
|
|
181
|
-
subclass.__new__ = functional.
|
|
200
|
+
subclass.__new__ = functional.sequence(subclass.__new__, functional.side_effect(on_subclass_new))
|
|
182
201
|
subclass.__bases__ = subclass.__bases__ + (InternalProxy,)
|
|
183
202
|
|
|
184
203
|
slots = { "__slots__": (), "__init_subclass__": init_subclass }
|
|
@@ -202,14 +221,6 @@ def extending_proxytype(cls, thread_state, ext_handler, int_handler, on_subclass
|
|
|
202
221
|
proxy = DescriptorProxy(handler = ext_handler, name = name, proxytype = extended)
|
|
203
222
|
setattr(extended, name, proxy)
|
|
204
223
|
|
|
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
224
|
if is_stub:
|
|
214
225
|
def __new__(cls, *args, **kwargs):
|
|
215
226
|
instance = utils.create_stub_object(cls)
|
retracesoftware/proxy/record.py
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
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.proxy.proxytype import dynamic_proxytype, superdict, is_descriptor, extending_proxytype, dynamic_int_proxytype, make_extensible
|
|
5
|
-
from retracesoftware.proxy.gateway import gateway_pair
|
|
5
|
+
from retracesoftware.proxy.proxytype import dynamic_proxytype, superdict, is_descriptor, extending_proxytype, dynamic_int_proxytype, make_extensible, Proxy
|
|
6
|
+
# from retracesoftware.proxy.gateway import gateway_pair
|
|
6
7
|
from retracesoftware.proxy.proxysystem import ProxySystem
|
|
7
|
-
|
|
8
|
+
from retracesoftware.proxy.thread import write_thread_switch
|
|
9
|
+
from retracesoftware.install.tracer import Tracer
|
|
8
10
|
import sys
|
|
11
|
+
import os
|
|
12
|
+
import types
|
|
13
|
+
|
|
14
|
+
class Placeholder:
|
|
15
|
+
__slots__ = ['id', '__weakref__']
|
|
16
|
+
|
|
17
|
+
def __init__(self, id):
|
|
18
|
+
self.id = id
|
|
9
19
|
|
|
10
20
|
class ExtendedProxy:
|
|
11
21
|
__slots__ = []
|
|
@@ -31,103 +41,184 @@ def keys_where_value(pred, dict):
|
|
|
31
41
|
for key,value in dict.items():
|
|
32
42
|
if pred(value): yield key
|
|
33
43
|
|
|
44
|
+
types_lookup = {v:k for k,v in types.__dict__.items() if isinstance(v, type)}
|
|
45
|
+
|
|
46
|
+
def resolve(obj):
|
|
47
|
+
try:
|
|
48
|
+
return getattr(sys.modules[obj.__module__], obj.__name__)
|
|
49
|
+
except:
|
|
50
|
+
return None
|
|
51
|
+
|
|
34
52
|
def resolveable(obj):
|
|
35
53
|
try:
|
|
36
54
|
return getattr(sys.modules[obj.__module__], obj.__name__) is obj
|
|
37
55
|
except:
|
|
38
56
|
return False
|
|
57
|
+
|
|
58
|
+
def resolveable_name(obj):
|
|
59
|
+
if obj in types_lookup:
|
|
60
|
+
return ('types', types_lookup[obj])
|
|
61
|
+
elif resolve(obj) is obj:
|
|
62
|
+
return (obj.__module__, obj.__name__)
|
|
63
|
+
else:
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
# when
|
|
67
|
+
class RecordProxySystem(ProxySystem):
|
|
39
68
|
|
|
40
|
-
|
|
69
|
+
def bind(self, obj):
|
|
70
|
+
self.bindings[obj] = self.writer.handle(Placeholder(self.next_placeholder_id))
|
|
71
|
+
self.writer(self.bindings[obj])
|
|
72
|
+
self.next_placeholder_id += 1
|
|
73
|
+
|
|
74
|
+
def before_fork(self):
|
|
75
|
+
self.writer.close()
|
|
76
|
+
super().before_fork()
|
|
77
|
+
# self.writer.path = self.dynamic_path
|
|
78
|
+
|
|
79
|
+
def after_fork_in_child(self):
|
|
80
|
+
new_path = self.new_child_path(self.writer.path)
|
|
81
|
+
new_path.parent.mkdir()
|
|
82
|
+
self.writer.path = new_path
|
|
83
|
+
super().after_fork_in_child()
|
|
84
|
+
|
|
85
|
+
def after_fork_in_parent(self):
|
|
86
|
+
super().after_fork_in_parent()
|
|
87
|
+
self.thread_state.value = self.saved_thread_state
|
|
88
|
+
self.writer.reopen()
|
|
89
|
+
|
|
90
|
+
def __init__(self, thread_state,
|
|
91
|
+
immutable_types,
|
|
92
|
+
tracing_config,
|
|
93
|
+
path):
|
|
94
|
+
|
|
95
|
+
self.fork_counter = 0
|
|
41
96
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
self.
|
|
97
|
+
self.getpid = thread_state.wrap(
|
|
98
|
+
desired_state = 'disabled', function = os.getpid)
|
|
99
|
+
|
|
100
|
+
self.pid = self.getpid()
|
|
46
101
|
|
|
47
|
-
|
|
48
|
-
|
|
102
|
+
self.writer = stream.writer(path)
|
|
103
|
+
|
|
104
|
+
w = self.writer.handle('TRACE')
|
|
105
|
+
def trace_writer(*args):
|
|
106
|
+
print(f'Trace: {args}')
|
|
107
|
+
w(*args)
|
|
49
108
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
109
|
+
self.extended_types = {}
|
|
110
|
+
self.bindings = utils.id_dict()
|
|
111
|
+
self.next_placeholder_id = 0
|
|
112
|
+
|
|
113
|
+
serialize = functional.walker(self.bindings.get_else_key)
|
|
114
|
+
|
|
115
|
+
thread_switch_monitor = \
|
|
116
|
+
utils.thread_switch_monitor(
|
|
117
|
+
functional.repeatedly(functional.sequence(utils.thread_id, self.writer)))
|
|
118
|
+
|
|
119
|
+
# self.sync = lambda function: functional.observer(on_call = functional.always(writer.handle('SYNC')), function = function)
|
|
120
|
+
self.sync = lambda function: functional.firstof(thread_switch_monitor, functional.always(self.writer.handle('SYNC')), function)
|
|
121
|
+
|
|
122
|
+
# trace_handle = writer.handle('TRACE')
|
|
123
|
+
# tracer = Tracer(tracing_config, writer = trace_handle)
|
|
124
|
+
|
|
125
|
+
# on_ext_result = writer.handle('RESULT')
|
|
126
|
+
# on_ext_result = functional.if_then_else(
|
|
127
|
+
# functional.isinstanceof(str), self.writer.handle('RESULT'), functional.sequence(serialize, self.writer))
|
|
128
|
+
|
|
129
|
+
# on_int_call = functional.mapargs(transform = serialize, function = self.writer.handle('CALL'))
|
|
66
130
|
|
|
67
|
-
|
|
131
|
+
error = self.writer.handle('ERROR')
|
|
68
132
|
|
|
69
|
-
|
|
70
|
-
|
|
133
|
+
def write_error(cls, val, traceback):
|
|
134
|
+
error(cls, val)
|
|
71
135
|
|
|
136
|
+
self.set_thread_id = functional.partial(utils.set_thread_id, self.writer)
|
|
72
137
|
|
|
73
|
-
|
|
74
|
-
class RecordProxySystem(ProxySystem):
|
|
75
|
-
|
|
76
|
-
def __init__(self, thread_state, immutable_types, tracer, writer):
|
|
77
|
-
super().__init__(thread_state = thread_state)
|
|
138
|
+
def watch(f): return functional.either(thread_switch_monitor, f)
|
|
78
139
|
|
|
79
|
-
|
|
140
|
+
tracer = Tracer(tracing_config, writer = trace_writer)
|
|
80
141
|
|
|
81
|
-
self
|
|
82
|
-
self
|
|
83
|
-
|
|
142
|
+
# def wrap_int_to_ext(self, obj): return obj
|
|
143
|
+
# def wrap_ext_to_int(self, obj): return obj
|
|
144
|
+
|
|
145
|
+
# def on_int_call(self, func, *args, **kwargs):
|
|
146
|
+
# pass
|
|
84
147
|
|
|
85
|
-
# on_ext_result
|
|
86
|
-
|
|
87
|
-
|
|
148
|
+
# def on_ext_result(self, result):
|
|
149
|
+
# pass
|
|
150
|
+
|
|
151
|
+
# def on_ext_error(self, err_type, err_value, err_tarceback):
|
|
152
|
+
# pass
|
|
88
153
|
|
|
89
|
-
def
|
|
90
|
-
|
|
154
|
+
# def ext_apply(self, func, *args, **kwargs):
|
|
155
|
+
# return func(*args, **kwargs)
|
|
91
156
|
|
|
92
|
-
def
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
error = writer.handle('ERROR')
|
|
157
|
+
# def int_apply(self, func, *args, **kwargs):
|
|
158
|
+
# return func(*args, **kwargs)
|
|
96
159
|
|
|
97
|
-
|
|
98
|
-
|
|
160
|
+
self.wrap_int_to_ext = watch
|
|
161
|
+
|
|
162
|
+
self.on_int_call = functional.mapargs(transform = serialize, function = self.writer.handle('CALL'))
|
|
163
|
+
|
|
164
|
+
self.on_ext_result = functional.if_then_else(
|
|
165
|
+
functional.isinstanceof(str),
|
|
166
|
+
self.writer.handle('RESULT'),
|
|
167
|
+
functional.sequence(serialize, self.writer))
|
|
168
|
+
|
|
169
|
+
self.on_ext_error = write_error
|
|
99
170
|
|
|
100
|
-
self.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
171
|
+
self.ext_apply = self.int_apply = functional.apply
|
|
172
|
+
|
|
173
|
+
super().__init__(thread_state = thread_state, tracer = tracer, immutable_types = immutable_types)
|
|
174
|
+
# wrap_int_to_ext = watch,
|
|
175
|
+
# on_int_call = on_int_call,
|
|
176
|
+
# on_ext_result = on_ext_result,
|
|
177
|
+
# on_ext_error = write_error)
|
|
178
|
+
|
|
179
|
+
# self.ext_handler, self.int_handler = gateway_pair(
|
|
180
|
+
# thread_state,
|
|
181
|
+
# self.tracer,
|
|
182
|
+
# immutable_types = immutable_types,
|
|
183
|
+
# wrap_int_to_ext = watch,
|
|
184
|
+
# int_proxytype = self.int_proxytype,
|
|
185
|
+
# ext_proxytype = self.proxytype,
|
|
186
|
+
# on_int_call = on_int_call,
|
|
187
|
+
# on_ext_result = on_ext_result,
|
|
188
|
+
# on_ext_error = write_error)
|
|
189
|
+
|
|
190
|
+
def ext_proxytype(self, cls):
|
|
191
|
+
assert isinstance(cls, type), f"record.proxytype requires a type but was passed: {cls}"
|
|
192
|
+
|
|
193
|
+
# resolved = resolve(cls)
|
|
194
|
+
|
|
195
|
+
proxytype = super().ext_proxytype(cls)
|
|
196
|
+
|
|
197
|
+
if resolveable_name(cls):
|
|
198
|
+
module, name = resolveable_name(cls)
|
|
199
|
+
ref = self.writer.handle(ProxyRef(name = name, module = module))
|
|
200
|
+
else:
|
|
201
|
+
blacklist = ['__getattribute__']
|
|
202
|
+
descriptors = {k: v for k,v in superdict(cls).items() if k not in blacklist and is_descriptor(v) }
|
|
203
|
+
|
|
204
|
+
methods = [k for k, v in descriptors.items() if utils.is_method_descriptor(v)]
|
|
205
|
+
members = [k for k, v in descriptors.items() if not utils.is_method_descriptor(v)]
|
|
206
|
+
|
|
207
|
+
ref = self.writer.handle(ProxySpec(name = cls.__name__,
|
|
208
|
+
module = cls.__module__,
|
|
209
|
+
methods = methods,
|
|
210
|
+
members = members))
|
|
211
|
+
|
|
212
|
+
self.writer.type_serializer[proxytype] = functional.constantly(ref)
|
|
213
|
+
return proxytype
|
|
109
214
|
|
|
110
215
|
def extend_type(self, base):
|
|
111
216
|
|
|
112
217
|
if base in self.extended_types:
|
|
113
218
|
return self.extended_types[base]
|
|
114
219
|
|
|
115
|
-
|
|
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)
|
|
220
|
+
extended = super().extend_type(base)
|
|
127
221
|
|
|
128
|
-
# make_extensible(cls = extended, handler = self.int_handler, on_new = self.writer.placeholder)
|
|
129
|
-
|
|
130
|
-
self.immutable_types.add(extended)
|
|
131
222
|
self.extended_types[base] = extended
|
|
132
223
|
|
|
133
224
|
return extended
|