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
retracesoftware/config.json
CHANGED
|
@@ -164,6 +164,9 @@
|
|
|
164
164
|
"sys": {
|
|
165
165
|
"with_state": {
|
|
166
166
|
"disabled": ["excepthook"]
|
|
167
|
+
},
|
|
168
|
+
"with_state_recursive0": {
|
|
169
|
+
"disabled": ["settrace", "setprofile"]
|
|
167
170
|
}
|
|
168
171
|
},
|
|
169
172
|
|
|
@@ -293,6 +296,10 @@
|
|
|
293
296
|
"_path_normpath"
|
|
294
297
|
],
|
|
295
298
|
|
|
299
|
+
"with_state_recursive0": {
|
|
300
|
+
"disabled": ["register_at_fork"]
|
|
301
|
+
},
|
|
302
|
+
|
|
296
303
|
"wrappers": {
|
|
297
304
|
"fork_exec": "retracesoftware.install.edgecases.fork_exec",
|
|
298
305
|
"posix_spawn": "retracesoftware.install.edgecases.posix_spawn"
|
|
@@ -58,7 +58,7 @@ class MethodDescriptor:
|
|
|
58
58
|
self.cls = descriptor.__objclass__
|
|
59
59
|
self.name = descriptor.name
|
|
60
60
|
|
|
61
|
-
def once(*args): return functional.memoize_one_arg(functional.
|
|
61
|
+
def once(*args): return functional.memoize_one_arg(functional.sequence(*args))
|
|
62
62
|
|
|
63
63
|
any = functional.firstof
|
|
64
64
|
|
|
@@ -121,7 +121,7 @@ def replaying_proxy_factory(thread_state, is_immutable_type, tracer, next, bind,
|
|
|
121
121
|
on_call = tracer('proxy.ext.call'),
|
|
122
122
|
on_result = tracer('proxy.ext.result'),
|
|
123
123
|
on_error = tracer('proxy.ext.error'),
|
|
124
|
-
function = functional.
|
|
124
|
+
function = functional.sequence(functional.always(next), create_stubs))
|
|
125
125
|
|
|
126
126
|
return ProxyFactory(thread_state = thread_state,
|
|
127
127
|
is_immutable_type = is_immutable_type,
|
|
@@ -131,30 +131,6 @@ def replaying_proxy_factory(thread_state, is_immutable_type, tracer, next, bind,
|
|
|
131
131
|
wrap_int_call = wrap_int_call,
|
|
132
132
|
wrap_ext_call = wrap_ext_call)
|
|
133
133
|
|
|
134
|
-
def latest_from_pattern(pattern: str) -> str | None:
|
|
135
|
-
"""
|
|
136
|
-
Given a strftime-style filename pattern (e.g. "recordings/%Y%m%d_%H%M%S_%f"),
|
|
137
|
-
return the path to the most recent matching file, or None if no files exist.
|
|
138
|
-
"""
|
|
139
|
-
# Turn strftime placeholders into '*' for globbing
|
|
140
|
-
# (very simple replacement: %... -> *)
|
|
141
|
-
glob_pattern = re.sub(r"%[a-zA-Z]", "*", pattern)
|
|
142
|
-
|
|
143
|
-
# Find all matching files
|
|
144
|
-
candidates = glob.glob(glob_pattern)
|
|
145
|
-
if not candidates:
|
|
146
|
-
return None
|
|
147
|
-
|
|
148
|
-
# Derive the datetime format from the pattern (basename only)
|
|
149
|
-
base_pattern = os.path.basename(pattern)
|
|
150
|
-
|
|
151
|
-
def parse_time(path: str):
|
|
152
|
-
name = os.path.basename(path)
|
|
153
|
-
return datetime.strptime(name, base_pattern)
|
|
154
|
-
|
|
155
|
-
# Find the latest by parsed timestamp
|
|
156
|
-
latest = max(candidates, key=parse_time)
|
|
157
|
-
return latest
|
|
158
134
|
|
|
159
135
|
# class Reader:
|
|
160
136
|
|
|
@@ -24,7 +24,7 @@ from retracesoftware.install.config import load_config
|
|
|
24
24
|
|
|
25
25
|
from functools import wraps
|
|
26
26
|
|
|
27
|
-
import
|
|
27
|
+
import retracesoftware.functional as functional
|
|
28
28
|
import retracesoftware_utils as utils
|
|
29
29
|
|
|
30
30
|
from retracesoftware.install import edgecases
|
|
@@ -158,13 +158,14 @@ def wrap_method_descriptors(wrapper, prefix, base):
|
|
|
158
158
|
class Patcher:
|
|
159
159
|
|
|
160
160
|
def __init__(self, thread_state, config, system,
|
|
161
|
-
immutable_types,
|
|
161
|
+
immutable_types,
|
|
162
162
|
on_function_proxy = None,
|
|
163
163
|
debug_level = 0,
|
|
164
164
|
post_commit = None):
|
|
165
165
|
|
|
166
166
|
# validate(config)
|
|
167
|
-
|
|
167
|
+
# system.set_thread_id(0)
|
|
168
|
+
# utils.set_thread_id(0)
|
|
168
169
|
self.thread_counter = system.sync(utils.counter(1))
|
|
169
170
|
# self.set_thread_number = set_thread_number
|
|
170
171
|
|
|
@@ -217,6 +218,7 @@ class Patcher:
|
|
|
217
218
|
for name in spec:
|
|
218
219
|
if name in mod_dict:
|
|
219
220
|
if isinstance(mod_dict[name], type):
|
|
221
|
+
assert isinstance(mod_dict[name], type)
|
|
220
222
|
self.immutable_types_set.add(mod_dict[name])
|
|
221
223
|
else:
|
|
222
224
|
raise Exception(f'Tried to add "{name}" - {mod_dict[name]} which isn\'t a type to immutable')
|
|
@@ -264,7 +266,7 @@ class Patcher:
|
|
|
264
266
|
|
|
265
267
|
def threadrunner(*args, **kwargs):
|
|
266
268
|
nonlocal thread_id
|
|
267
|
-
|
|
269
|
+
self.system.set_thread_id(thread_id)
|
|
268
270
|
|
|
269
271
|
with self.thread_state.select('internal'):
|
|
270
272
|
# if self.tracing:
|
|
@@ -304,6 +306,23 @@ class Patcher:
|
|
|
304
306
|
def sync_types(self, value):
|
|
305
307
|
return wrap_method_descriptors(self.system.sync, "retrace", value)
|
|
306
308
|
|
|
309
|
+
@phase
|
|
310
|
+
def with_state_recursive(self, spec, mod_dict):
|
|
311
|
+
|
|
312
|
+
updates = {}
|
|
313
|
+
|
|
314
|
+
for state,elems in spec.items():
|
|
315
|
+
|
|
316
|
+
def wrap(obj):
|
|
317
|
+
return functional.recursive_wrap(
|
|
318
|
+
callable,
|
|
319
|
+
lambda f: self.thread_state.wrap(state, f),
|
|
320
|
+
obj)
|
|
321
|
+
|
|
322
|
+
updates.update(map_values(wrap, select_keys(elems, mod_dict)))
|
|
323
|
+
|
|
324
|
+
return updates
|
|
325
|
+
|
|
307
326
|
@phase
|
|
308
327
|
def with_state(self, spec, mod_dict):
|
|
309
328
|
|
|
@@ -342,7 +361,7 @@ class Patcher:
|
|
|
342
361
|
assert callable(param)
|
|
343
362
|
|
|
344
363
|
return functional.if_then_else(
|
|
345
|
-
test = functional.
|
|
364
|
+
test = functional.sequence(param, self.path_predicate),
|
|
346
365
|
then = func,
|
|
347
366
|
otherwise = self.thread_state.wrap('disabled', func))
|
|
348
367
|
|
|
@@ -356,13 +375,14 @@ class Patcher:
|
|
|
356
375
|
name = parts[0]
|
|
357
376
|
if name in mod_dict:
|
|
358
377
|
value = mod_dict[name]
|
|
359
|
-
|
|
378
|
+
assert not isinstance(value, utils.wrapped_function), f"value for key: {name} is already wrapped"
|
|
360
379
|
if len(parts) == 1:
|
|
361
380
|
updates[name] = resolve(wrapper_name)(value)
|
|
362
381
|
elif len(parts) == 2:
|
|
363
382
|
member = getattr(value, parts[1], None)
|
|
364
383
|
if member:
|
|
365
|
-
|
|
384
|
+
new_value = resolve(wrapper_name)(member)
|
|
385
|
+
setattr(value, parts[1], new_value)
|
|
366
386
|
else:
|
|
367
387
|
raise Exception('TODO')
|
|
368
388
|
|
|
@@ -463,6 +483,10 @@ def install(mode):
|
|
|
463
483
|
immutable_types = immutable_types,
|
|
464
484
|
config = config)
|
|
465
485
|
|
|
486
|
+
os.register_at_fork(before = system.before_fork,
|
|
487
|
+
after_in_parent = system.after_fork_in_parent,
|
|
488
|
+
after_in_child = system.after_fork_in_child)
|
|
489
|
+
|
|
466
490
|
patcher = Patcher(thread_state = thread_state,
|
|
467
491
|
config = config,
|
|
468
492
|
system = system,
|
|
@@ -13,6 +13,10 @@ from datetime import datetime
|
|
|
13
13
|
import json
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
|
+
class ThreadSwitch:
|
|
17
|
+
def __init__(self, id):
|
|
18
|
+
self.id = id
|
|
19
|
+
|
|
16
20
|
def write_files(recording_path):
|
|
17
21
|
with open(recording_path / 'env', 'w') as f:
|
|
18
22
|
json.dump(dict(os.environ), f, indent=2)
|
|
@@ -38,10 +42,6 @@ def tracing_level(config):
|
|
|
38
42
|
# level = os.environ.get('RETRACE_DEBUG', config['default_tracing_level'])
|
|
39
43
|
# return config['tracing_levels'].get(level, {})
|
|
40
44
|
|
|
41
|
-
def thread_aware_writer(writer):
|
|
42
|
-
on_thread_switch = functional.sequence(utils.thread_id(), writer.handle('THREAD_SWITCH'))
|
|
43
|
-
return utils.threadawareproxy(on_thread_switch = on_thread_switch, target = writer)
|
|
44
|
-
|
|
45
45
|
def record_system(thread_state, immutable_types, config):
|
|
46
46
|
|
|
47
47
|
recording_path = create_recording_path(config['recording_path'])
|
|
@@ -57,7 +57,7 @@ def record_system(thread_state, immutable_types, config):
|
|
|
57
57
|
with open(recording_path / 'tracing_config.json', 'w') as f:
|
|
58
58
|
json.dump(tracing_config, f, indent=2)
|
|
59
59
|
|
|
60
|
-
writer =
|
|
60
|
+
# writer = stream.writer(path = recording_path / 'trace.bin')
|
|
61
61
|
|
|
62
62
|
# os.register_at_fork(
|
|
63
63
|
# # before = self.thread_state.wrap('disabled', self.before_fork),
|
|
@@ -86,43 +86,11 @@ def record_system(thread_state, immutable_types, config):
|
|
|
86
86
|
# self.gc_end()
|
|
87
87
|
# gc.callbacks.append(self.gc_hook)
|
|
88
88
|
|
|
89
|
-
w = writer.handle('TRACE')
|
|
90
|
-
def trace_writer(*args):
|
|
91
|
-
print(f'Trace: {args}')
|
|
92
|
-
w(*args)
|
|
93
|
-
|
|
94
89
|
# print(f'Tracing config: {tracing_config(config)}')
|
|
95
90
|
|
|
96
|
-
tracer = Tracer(tracing_config, writer = trace_writer)
|
|
97
91
|
# tracer = Tracer(config = tracing_config(config), writer = writer.handle('TRACE'))
|
|
98
92
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
# factory.proxy_type = compose(factory.proxy_type, side_effect(...))
|
|
105
|
-
|
|
106
|
-
def on_patched(module_name, updates):
|
|
107
|
-
...
|
|
108
|
-
# for name, value in updates.items():
|
|
109
|
-
# if isinstance(value, type) and \
|
|
110
|
-
# issubclass(value, ExtendingProxy) and \
|
|
111
|
-
# not issubclass(value, InternalProxy):
|
|
112
|
-
|
|
113
|
-
# ref = writer.handle(ExtendingProxySpec(module = module_name, name = name))
|
|
114
|
-
# try:
|
|
115
|
-
# writer.add_type_serializer(cls = value, serializer = functional.constantly(ref))
|
|
116
|
-
# except:
|
|
117
|
-
# pass
|
|
118
|
-
|
|
119
|
-
factory.on_patched = on_patched
|
|
120
|
-
|
|
121
|
-
factory.sync = lambda function: functional.observer(on_call = functional.always(writer.handle('SYNC')), function = function)
|
|
122
|
-
|
|
123
|
-
# factory.set_thread_number = writer.thread_number
|
|
124
|
-
factory.tracer = tracer
|
|
125
|
-
|
|
126
|
-
factory.log = functional.partial(writer, 'LOG')
|
|
127
|
-
|
|
128
|
-
return factory
|
|
93
|
+
return RecordProxySystem(thread_state = thread_state,
|
|
94
|
+
immutable_types = immutable_types,
|
|
95
|
+
tracing_config = tracing_config,
|
|
96
|
+
path = recording_path / 'trace.bin')
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
from retracesoftware.proxy import *
|
|
2
2
|
|
|
3
|
-
import retracesoftware.functional as functional
|
|
4
|
-
import retracesoftware_utils as utils
|
|
5
|
-
import retracesoftware.stream as stream
|
|
6
|
-
from retracesoftware.install.tracer import Tracer
|
|
7
3
|
from retracesoftware.install import globals
|
|
8
4
|
|
|
9
|
-
import os, json, re, glob
|
|
5
|
+
import os, json, re, glob
|
|
10
6
|
from pathlib import Path
|
|
11
7
|
from datetime import datetime
|
|
12
8
|
|
|
@@ -35,15 +31,6 @@ def latest_from_pattern(pattern: str) -> str | None:
|
|
|
35
31
|
latest = max(candidates, key=parse_time)
|
|
36
32
|
return latest
|
|
37
33
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def thread_aware_reader(reader):
|
|
41
|
-
def on_thread_switch():
|
|
42
|
-
...
|
|
43
|
-
|
|
44
|
-
return utils.threadawareproxy(on_thread_switch = on_thread_switch, target = reader)
|
|
45
|
-
|
|
46
|
-
|
|
47
34
|
def replay_system(thread_state, immutable_types, config):
|
|
48
35
|
|
|
49
36
|
recording_path = Path(latest_from_pattern(config['recording_path']))
|
|
@@ -61,91 +48,7 @@ def replay_system(thread_state, immutable_types, config):
|
|
|
61
48
|
with open(recording_path / "tracing_config.json", "r", encoding="utf-8") as f:
|
|
62
49
|
tracing_config = json.load(f)
|
|
63
50
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
# def create_stub_type(proxyspec):
|
|
67
|
-
# if isinstance(proxyspec, ExtendingProxySpec):
|
|
68
|
-
# mod = sys.modules[proxyspec.module]
|
|
69
|
-
# resolved = getattr(mod, proxyspec.name)
|
|
70
|
-
# assert issubclass(resolved, ExtendingProxy)
|
|
71
|
-
|
|
72
|
-
# return resolved
|
|
73
|
-
# # unproxied = resolved.__base__
|
|
74
|
-
# # print(f'base: {unproxied} has_generic_new: {utils.has_generic_new(unproxied)}')
|
|
75
|
-
# # print(f'base: {unproxied} has_generic_alloc: {utils.has_generic_alloc(unproxied)}')
|
|
76
|
-
# # utils.create_stub_object(resolved)
|
|
77
|
-
# # os._exit(1)
|
|
78
|
-
# # return resolved
|
|
79
|
-
|
|
80
|
-
# elif isinstance(proxyspec, WrappingProxySpec):
|
|
81
|
-
# nonlocal handler
|
|
82
|
-
# return proxyspec.create_type(handler)
|
|
83
|
-
# else:
|
|
84
|
-
# print(f'In create_stub_type!!!! {proxyspec}')
|
|
85
|
-
# os._exit(1)
|
|
86
|
-
|
|
87
|
-
# deserializer = functional.compose(pickle.loads, functional.when_instanceof(ProxySpec, create_stub_type))
|
|
88
|
-
|
|
89
|
-
reader = thread_aware_reader(stream.reader(path = recording_path / 'trace.bin'))
|
|
90
|
-
|
|
91
|
-
# reader = utils.threadawareproxy(on_thread_switch = ..., target = reader)
|
|
92
|
-
|
|
93
|
-
def readnext():
|
|
94
|
-
return reader()
|
|
95
|
-
# print(f'read: {obj}')
|
|
96
|
-
# return obj
|
|
97
|
-
|
|
98
|
-
lookup = weakref.WeakKeyDictionary()
|
|
99
|
-
|
|
100
|
-
# debug = debug_level(config)
|
|
101
|
-
|
|
102
|
-
# int_refs = {}
|
|
103
|
-
|
|
104
|
-
def checkpoint(replay):
|
|
105
|
-
...
|
|
106
|
-
|
|
107
|
-
def read_required(required):
|
|
108
|
-
obj = readnext()
|
|
109
|
-
if obj != required:
|
|
110
|
-
print(f'Expected: {required} but got: {obj}')
|
|
111
|
-
for i in range(5):
|
|
112
|
-
readnext()
|
|
113
|
-
|
|
114
|
-
utils.sigtrap(None)
|
|
115
|
-
os._exit(1)
|
|
116
|
-
raise Exception(f'Expected: {required} but got: {obj}')
|
|
117
|
-
|
|
118
|
-
def trace_writer(name, *args):
|
|
119
|
-
print(f'Trace: {name} {args}')
|
|
120
|
-
|
|
121
|
-
read_required('TRACE')
|
|
122
|
-
read_required(name)
|
|
123
|
-
|
|
124
|
-
for arg in args:
|
|
125
|
-
read_required(arg)
|
|
126
|
-
|
|
127
|
-
tracer = Tracer(tracing_config, writer = trace_writer)
|
|
128
|
-
|
|
129
|
-
factory = ReplayProxySystem(thread_state = thread_state,
|
|
51
|
+
return ReplayProxySystem(thread_state = thread_state,
|
|
130
52
|
immutable_types = immutable_types,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
# factory = replaying_proxy_factory(thread_state = thread_state,
|
|
135
|
-
# is_immutable_type = is_immutable_type,
|
|
136
|
-
# tracer = tracer,
|
|
137
|
-
# bind = reader.supply,
|
|
138
|
-
# next = next_result,
|
|
139
|
-
# checkpoint = checkpoint)
|
|
140
|
-
|
|
141
|
-
factory.tracer = tracer
|
|
142
|
-
|
|
143
|
-
def read_sync(): read_required('SYNC')
|
|
144
|
-
|
|
145
|
-
factory.sync = lambda function: functional.observer(on_call = functional.always(read_sync), function = function)
|
|
146
|
-
|
|
147
|
-
# factory.set_thread_number = writer.thread_number
|
|
148
|
-
|
|
149
|
-
factory.log = lambda message: checkpoint({'type': 'log_message', 'message': message})
|
|
150
|
-
|
|
151
|
-
return factory
|
|
53
|
+
tracing_config = tracing_config,
|
|
54
|
+
path = recording_path / 'trace.bin')
|
|
@@ -120,7 +120,7 @@ class Tracer:
|
|
|
120
120
|
writer = functional.partial(self.writer, name)
|
|
121
121
|
|
|
122
122
|
if name in self.config:
|
|
123
|
-
return functional.
|
|
123
|
+
return functional.sequence(func, functional.side_effect(writer))
|
|
124
124
|
else:
|
|
125
125
|
return func
|
|
126
126
|
|
|
@@ -139,6 +139,6 @@ class Tracer:
|
|
|
139
139
|
|
|
140
140
|
def event_after(self, name, func):
|
|
141
141
|
if name in self.config:
|
|
142
|
-
return functional.
|
|
142
|
+
return functional.sequence(func, functional.side_effect(self.event(name)))
|
|
143
143
|
else:
|
|
144
144
|
return func
|
retracesoftware/proxy/gateway.py
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import retracesoftware.functional as functional
|
|
2
2
|
import retracesoftware_utils as utils
|
|
3
3
|
|
|
4
|
+
from retracesoftware.proxy.proxytype import ExtendingProxy
|
|
5
|
+
|
|
4
6
|
# from retracesoftware.proxy.proxytype import ExtendingProxy
|
|
5
7
|
|
|
6
|
-
unproxy_execute = functional.mapargs(starting = 1,
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
# unproxy_execute = functional.mapargs(starting = 1,
|
|
9
|
+
# transform = functional.walker(utils.try_unwrap),
|
|
10
|
+
# function = functional.apply)
|
|
9
11
|
|
|
10
12
|
def adapter(proxy_input,
|
|
11
13
|
proxy_output,
|
|
@@ -16,85 +18,141 @@ def adapter(proxy_input,
|
|
|
16
18
|
|
|
17
19
|
# function = functional.apply
|
|
18
20
|
|
|
19
|
-
if on_call: function =
|
|
21
|
+
if on_call: function = utils.observer(on_call = on_call, function = function)
|
|
22
|
+
|
|
23
|
+
#functional.observer(on_call = on_call, function = function)
|
|
20
24
|
|
|
21
25
|
function = functional.mapargs(starting = 1, transform = proxy_input, function = function)
|
|
22
26
|
|
|
23
|
-
function = functional.
|
|
27
|
+
function = functional.sequence(function, proxy_output)
|
|
24
28
|
|
|
25
29
|
if on_result or on_error:
|
|
26
|
-
function =
|
|
30
|
+
function = utils.observer(on_result = on_result, on_error = on_error, function = function)
|
|
27
31
|
|
|
28
32
|
return function
|
|
29
33
|
|
|
30
|
-
def
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
# def callbacks():
|
|
35
|
+
# return {
|
|
36
|
+
# 'proxy': None
|
|
37
|
+
# 'proxytype': None,
|
|
38
|
+
# 'on_call': None,
|
|
39
|
+
# 'on_result': None,
|
|
40
|
+
# 'on_error': None,
|
|
41
|
+
# 'apply': functional.apply,
|
|
42
|
+
# }
|
|
43
|
+
|
|
44
|
+
def adapter_pair1(int, ext):
|
|
38
45
|
return (
|
|
39
46
|
adapter(
|
|
40
|
-
function =
|
|
41
|
-
proxy_input =
|
|
42
|
-
proxy_output =
|
|
43
|
-
on_call =
|
|
44
|
-
on_result =
|
|
45
|
-
on_error =
|
|
46
|
-
# on_result = tracer('proxy.ext.result', on_ext_result),
|
|
47
|
-
# on_error = tracer('proxy.ext.error', on_ext_error)),
|
|
47
|
+
function = ext.apply,
|
|
48
|
+
proxy_input = int.proxy,
|
|
49
|
+
proxy_output = ext.proxy,
|
|
50
|
+
on_call = ext.on_call,
|
|
51
|
+
on_result = ext.on_result,
|
|
52
|
+
on_error = ext.on_error),
|
|
48
53
|
adapter(
|
|
49
|
-
function =
|
|
50
|
-
proxy_input =
|
|
51
|
-
proxy_output =
|
|
52
|
-
on_call =
|
|
53
|
-
on_result =
|
|
54
|
-
on_error =
|
|
54
|
+
function = int.apply,
|
|
55
|
+
proxy_input = ext.proxy,
|
|
56
|
+
proxy_output = int.proxy,
|
|
57
|
+
on_call = int.on_call,
|
|
58
|
+
on_result = int.on_result,
|
|
59
|
+
on_error = int.on_error))
|
|
60
|
+
|
|
61
|
+
# def adapter_pair(proxy_int,
|
|
62
|
+
# proxy_ext,
|
|
63
|
+
# int_apply,
|
|
64
|
+
# ext_apply,
|
|
65
|
+
# tracer,
|
|
66
|
+
# on_int_call,
|
|
67
|
+
# on_ext_result,
|
|
68
|
+
# on_ext_error):
|
|
69
|
+
# return (
|
|
70
|
+
# adapter(
|
|
71
|
+
# function = ext_apply,
|
|
72
|
+
# proxy_input = proxy_int,
|
|
73
|
+
# proxy_output = proxy_ext,
|
|
74
|
+
# on_call = tracer('proxy.ext.call'),
|
|
75
|
+
# on_result = on_ext_result,
|
|
76
|
+
# on_error = on_ext_error),
|
|
77
|
+
# # on_result = tracer('proxy.ext.result', on_ext_result),
|
|
78
|
+
# # on_error = tracer('proxy.ext.error', on_ext_error)),
|
|
79
|
+
# adapter(
|
|
80
|
+
# function = int_apply,
|
|
81
|
+
# proxy_input = proxy_ext,
|
|
82
|
+
# proxy_output = proxy_int,
|
|
83
|
+
# on_call = tracer('proxy.int.call', on_int_call),
|
|
84
|
+
# on_result = tracer('proxy.int.result'),
|
|
85
|
+
# on_error = tracer('proxy.int.error')))
|
|
86
|
+
|
|
87
|
+
# def proxy(proxytype):
|
|
88
|
+
# def set_type(cls, obj):
|
|
89
|
+
# obj.__class__ = cls
|
|
90
|
+
# return obj
|
|
91
|
+
|
|
92
|
+
# def can_set_type(cls, obj): return issubclass(cls, ExtendingProxy)
|
|
93
|
+
|
|
94
|
+
# create = functional.if_then_else(can_set_type, set_type, utils.create_wrapped)
|
|
95
|
+
|
|
96
|
+
# return functional.spread(
|
|
97
|
+
# create,
|
|
98
|
+
# functional.sequence(functional.typeof, proxytype),
|
|
99
|
+
# None)
|
|
100
|
+
|
|
101
|
+
# functional.sequence(functional.typeof, proxytype)
|
|
102
|
+
# lambda obj: functional.partial(utils.create_wrapped(proxytype(type(obj)))
|
|
103
|
+
# return lambda obj: utils.create_wrapped(proxytype(type(obj)), obj)
|
|
104
|
+
# return functional.selfapply(functional.sequence(functional.typeof, proxytype))
|
|
105
|
+
|
|
106
|
+
# def maybe_proxy(proxytype):
|
|
107
|
+
# return functional.if_then_else(
|
|
108
|
+
# functional.isinstanceof(utils.Wrapped),
|
|
109
|
+
# utils.unwrap,
|
|
110
|
+
# proxy(functional.memoize_one_arg(proxytype)))
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# def gateway_pair(thread_state,
|
|
114
|
+
# tracer,
|
|
115
|
+
# immutable_types,
|
|
116
|
+
# int_proxytype,
|
|
117
|
+
# ext_proxytype,
|
|
118
|
+
# wrap_int_to_ext = functional.identity,
|
|
119
|
+
# int_apply = functional.apply,
|
|
120
|
+
# ext_apply = functional.apply,
|
|
121
|
+
# on_int_call = None,
|
|
122
|
+
# on_ext_result = None,
|
|
123
|
+
# on_ext_error = None):
|
|
124
|
+
|
|
125
|
+
# def is_immutable_type(cls):
|
|
126
|
+
# return issubclass(cls, tuple(immutable_types))
|
|
127
|
+
|
|
128
|
+
# is_immutable = functional.sequence(functional.typeof, functional.memoize_one_arg(is_immutable_type))
|
|
129
|
+
|
|
130
|
+
# def proxyfactory(proxytype):
|
|
131
|
+
# return functional.walker(functional.when_not(is_immutable, maybe_proxy(proxytype)))
|
|
55
132
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
on_int_call = None,
|
|
73
|
-
on_ext_result = None,
|
|
74
|
-
on_ext_error = None):
|
|
75
|
-
|
|
76
|
-
def is_immutable_type(cls):
|
|
77
|
-
return issubclass(cls, tuple(immutable_types))
|
|
78
|
-
|
|
79
|
-
is_immutable = functional.sequence(functional.typeof, functional.memoize_one_arg(is_immutable_type))
|
|
80
|
-
|
|
81
|
-
def create_proxier(proxytype):
|
|
82
|
-
return functional.walker(functional.when_not(is_immutable, maybe_proxy(proxytype)))
|
|
133
|
+
# # int_to_ext_dispatch = thread_state.dispatch(tracer('proxy.int.disabled.event', unproxy_execute))
|
|
134
|
+
# # ext_to_int_dispatch = thread_state.dispatch(tracer('proxy.ext.disabled.event', unproxy_execute))
|
|
135
|
+
|
|
136
|
+
# int_to_ext, ext_to_int = adapter_pair(
|
|
137
|
+
# proxy_int = proxyfactory(int_proxytype),
|
|
138
|
+
# proxy_ext = proxyfactory(ext_proxytype),
|
|
139
|
+
# int_apply = thread_state.wrap(desired_state = 'internal', function = int_apply),
|
|
140
|
+
# ext_apply = thread_state.wrap(desired_state = 'external', function = ext_apply),
|
|
141
|
+
# tracer = tracer,
|
|
142
|
+
# on_int_call = on_int_call,
|
|
143
|
+
# on_ext_result = on_ext_result,
|
|
144
|
+
# on_ext_error = on_ext_error)
|
|
145
|
+
|
|
146
|
+
# # thread_state.set_dispatch(int_to_ext_dispatch, external = functional.apply, internal = wrap_int_to_ext(tracer('proxy.int_to_ext.stack', int_to_ext)))
|
|
147
|
+
# # thread_state.set_dispatch(int_to_ext_dispatch, external = functional.apply, internal = wrap_int_to_ext(int_to_ext))
|
|
148
|
+
# # thread_state.set_dispatch(ext_to_int_dispatch, internal = functional.apply, external = tracer('proxy.ext_to_int.wrap', ext_to_int))
|
|
83
149
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
int_to_ext, ext_to_int = adapter_pair(
|
|
88
|
-
proxy_int = create_proxier(int_proxytype(ext_to_int_dispatch)),
|
|
89
|
-
proxy_ext = create_proxier(ext_proxytype(int_to_ext_dispatch)),
|
|
90
|
-
int_apply = thread_state.wrap(desired_state = 'internal', function = int_apply),
|
|
91
|
-
ext_apply = thread_state.wrap(desired_state = 'external', function = ext_apply),
|
|
92
|
-
tracer = tracer,
|
|
93
|
-
on_int_call = on_int_call,
|
|
94
|
-
on_ext_result = on_ext_result,
|
|
95
|
-
on_ext_error = on_ext_error)
|
|
96
|
-
|
|
97
|
-
thread_state.set_dispatch(int_to_ext_dispatch, external = functional.apply, internal = tracer('proxy.int_to_ext.stack', int_to_ext))
|
|
98
|
-
thread_state.set_dispatch(ext_to_int_dispatch, internal = functional.apply, external = tracer('proxy.ext_to_int.wrap', ext_to_int))
|
|
150
|
+
# def gateway(name, internal = functional.apply, external = functional.apply):
|
|
151
|
+
# default = tracer(name, unproxy_execute)
|
|
152
|
+
# return thread_state.dispatch(default, internal = internal, external = external)
|
|
99
153
|
|
|
100
|
-
|
|
154
|
+
# return (gateway('proxy.int.disabled.event',
|
|
155
|
+
# internal = wrap_int_to_ext(int_to_ext)),
|
|
156
|
+
# gateway('proxy.ext.disabled.event',
|
|
157
|
+
# external = tracer('proxy.ext_to_int.wrap', ext_to_int)))
|
|
158
|
+
|