retracesoftware-proxy 0.1.1__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/install/patcher.py +21 -2
- retracesoftware/install/record.py +7 -0
- retracesoftware/install/tracer.py +16 -14
- retracesoftware/proxy/gateway.py +3 -112
- retracesoftware/proxy/proxyfactory.py +194 -194
- retracesoftware/proxy/proxysystem.py +88 -67
- retracesoftware/proxy/proxytype.py +213 -85
- retracesoftware/proxy/record.py +80 -83
- retracesoftware/proxy/replay.py +57 -33
- retracesoftware/proxy/stubfactory.py +141 -0
- retracesoftware/proxy/thread.py +1 -1
- {retracesoftware_proxy-0.1.1.dist-info → retracesoftware_proxy-0.1.2.dist-info}/METADATA +1 -1
- retracesoftware_proxy-0.1.2.dist-info/RECORD +27 -0
- retracesoftware_proxy-0.1.1.dist-info/RECORD +0 -26
- {retracesoftware_proxy-0.1.1.dist-info → retracesoftware_proxy-0.1.2.dist-info}/WHEEL +0 -0
- {retracesoftware_proxy-0.1.1.dist-info → retracesoftware_proxy-0.1.2.dist-info}/top_level.txt +0 -0
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
import retracesoftware.functional as functional
|
|
2
2
|
import retracesoftware_utils as utils
|
|
3
3
|
import types
|
|
4
|
-
from retracesoftware.proxy.gateway import
|
|
4
|
+
from retracesoftware.proxy.gateway import adapter_pair
|
|
5
5
|
from types import SimpleNamespace
|
|
6
|
-
from retracesoftware.proxy.proxytype import
|
|
6
|
+
from retracesoftware.proxy.proxytype import *
|
|
7
|
+
from retracesoftware.proxy.stubfactory import Stub
|
|
8
|
+
import sys
|
|
9
|
+
import gc
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
class RetraceError(Exception):
|
|
12
|
+
pass
|
|
9
13
|
|
|
10
14
|
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
15
|
return functional.spread(
|
|
20
|
-
|
|
16
|
+
utils.create_wrapped,
|
|
21
17
|
functional.sequence(functional.typeof, proxytype),
|
|
22
18
|
None)
|
|
23
19
|
|
|
@@ -31,9 +27,23 @@ unproxy_execute = functional.mapargs(starting = 1,
|
|
|
31
27
|
transform = functional.walker(utils.try_unwrap),
|
|
32
28
|
function = functional.apply)
|
|
33
29
|
|
|
30
|
+
def resolve(obj):
|
|
31
|
+
try:
|
|
32
|
+
return getattr(sys.modules[obj.__module__], obj.__name__)
|
|
33
|
+
except:
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
def is_function_type(cls):
|
|
37
|
+
return cls in [types.BuiltinFunctionType, types.FunctionType]
|
|
38
|
+
|
|
34
39
|
class ProxySystem:
|
|
35
40
|
|
|
36
|
-
def
|
|
41
|
+
def bind(self, obj): pass
|
|
42
|
+
|
|
43
|
+
def wrap_int_to_ext(self, obj):
|
|
44
|
+
return obj
|
|
45
|
+
# return functional.sequence(functional.side_effect(functional.repeatedly(gc.collect)), obj)
|
|
46
|
+
|
|
37
47
|
def wrap_ext_to_int(self, obj): return obj
|
|
38
48
|
|
|
39
49
|
def on_int_call(self, func, *args, **kwargs):
|
|
@@ -45,18 +55,13 @@ class ProxySystem:
|
|
|
45
55
|
def on_ext_error(self, err_type, err_value, err_traceback):
|
|
46
56
|
pass
|
|
47
57
|
|
|
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
58
|
def __init__(self, thread_state, immutable_types, tracer):
|
|
55
59
|
|
|
56
60
|
self.thread_state = thread_state
|
|
57
61
|
self.fork_counter = 0
|
|
58
62
|
self.tracer = tracer
|
|
59
63
|
self.immutable_types = immutable_types
|
|
64
|
+
self.on_proxytype = None
|
|
60
65
|
|
|
61
66
|
def is_immutable_type(cls):
|
|
62
67
|
return issubclass(cls, tuple(immutable_types))
|
|
@@ -67,53 +72,32 @@ class ProxySystem:
|
|
|
67
72
|
return functional.walker(functional.when_not(is_immutable, maybe_proxy(proxytype)))
|
|
68
73
|
|
|
69
74
|
int_spec = SimpleNamespace(
|
|
70
|
-
|
|
71
|
-
proxy = proxyfactory(self.int_proxytype),
|
|
75
|
+
apply = thread_state.wrap('internal', functional.apply),
|
|
76
|
+
proxy = proxyfactory(thread_state.wrap('disabled', self.int_proxytype)),
|
|
72
77
|
on_call = tracer('proxy.int.call', self.on_int_call),
|
|
73
78
|
on_result = tracer('proxy.int.result'),
|
|
74
79
|
on_error = tracer('proxy.int.error'),
|
|
75
|
-
apply = self.int_apply,
|
|
76
80
|
)
|
|
77
81
|
|
|
78
82
|
ext_spec = SimpleNamespace(
|
|
79
|
-
|
|
80
|
-
proxy = proxyfactory(self.
|
|
83
|
+
apply = thread_state.wrap('external', functional.apply),
|
|
84
|
+
proxy = proxyfactory(thread_state.wrap('disabled', self.dynamic_ext_proxytype)),
|
|
81
85
|
on_call = tracer('proxy.ext.call'),
|
|
82
86
|
on_result = self.on_ext_result,
|
|
83
87
|
on_error = self.on_ext_error,
|
|
84
|
-
apply = self.ext_apply
|
|
85
88
|
)
|
|
86
89
|
|
|
87
|
-
int2ext, ext2int =
|
|
88
|
-
|
|
89
|
-
# self.ext_handler = thread_state.dispatch(default, internal = internal, external = external)
|
|
90
|
+
int2ext, ext2int = adapter_pair(int_spec, ext_spec)
|
|
90
91
|
|
|
91
92
|
def gateway(name, internal = functional.apply, external = functional.apply):
|
|
92
93
|
default = tracer(name, unproxy_execute)
|
|
93
94
|
return thread_state.dispatch(default, internal = internal, external = external)
|
|
94
95
|
|
|
95
|
-
self.ext_handler =
|
|
96
|
-
self.int_handler =
|
|
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)
|
|
96
|
+
self.ext_handler = self.wrap_int_to_ext(int2ext)
|
|
97
|
+
self.int_handler = self.wrap_ext_to_int(ext2int)
|
|
116
98
|
|
|
99
|
+
self.ext_dispatch = gateway('proxy.int.disabled.event', internal = self.ext_handler)
|
|
100
|
+
self.int_dispatch = gateway('proxy.ext.disabled.event', external = self.int_handler)
|
|
117
101
|
|
|
118
102
|
def new_child_path(self, path):
|
|
119
103
|
return path.parent / f'fork-{self.fork_counter}' / path.name
|
|
@@ -134,48 +118,85 @@ class ProxySystem:
|
|
|
134
118
|
|
|
135
119
|
def int_proxytype(self, cls):
|
|
136
120
|
return dynamic_int_proxytype(
|
|
137
|
-
handler = self.
|
|
121
|
+
handler = self.int_dispatch,
|
|
138
122
|
cls = cls,
|
|
139
123
|
bind = self.bind)
|
|
140
124
|
|
|
125
|
+
def dynamic_ext_proxytype(self, cls):
|
|
126
|
+
print(f'dynamic_ext_proxytype: {cls} {self.thread_state.value}')
|
|
127
|
+
|
|
128
|
+
proxytype = dynamic_proxytype(
|
|
129
|
+
handler = self.ext_dispatch,
|
|
130
|
+
cls = cls)
|
|
131
|
+
if self.on_proxytype:
|
|
132
|
+
self.on_proxytype(proxytype)
|
|
133
|
+
|
|
134
|
+
return proxytype
|
|
135
|
+
|
|
136
|
+
# resolved = resolve(cls)
|
|
137
|
+
# if isinstance(resolved, ExtendingProxy):
|
|
138
|
+
# return dynamic_from_extended(resolved)
|
|
139
|
+
# elif isinstance(resolved, DynamicProxy):
|
|
140
|
+
# return resolved
|
|
141
|
+
# else:
|
|
142
|
+
# return dynamic_proxytype(handler = self.ext_dispatch, cls = cls)
|
|
143
|
+
|
|
141
144
|
def ext_proxytype(self, cls):
|
|
142
145
|
assert isinstance(cls, type)
|
|
143
146
|
if utils.is_extendable(cls):
|
|
144
147
|
return self.extend_type(cls)
|
|
145
148
|
else:
|
|
146
149
|
return instantiable_dynamic_proxytype(
|
|
147
|
-
handler = self.
|
|
150
|
+
handler = self.ext_dispatch,
|
|
148
151
|
cls = cls,
|
|
149
152
|
thread_state = self.thread_state,
|
|
150
153
|
create_stub = self.create_stub())
|
|
151
154
|
|
|
152
|
-
def extend_type(self,
|
|
155
|
+
def extend_type(self, cls):
|
|
153
156
|
|
|
154
157
|
extended = extending_proxytype(
|
|
155
|
-
cls =
|
|
158
|
+
cls = cls,
|
|
159
|
+
base = Stub if self.create_stub() else cls,
|
|
156
160
|
thread_state = self.thread_state,
|
|
157
|
-
ext_handler = self.
|
|
158
|
-
int_handler = self.
|
|
159
|
-
on_subclass_new = self.bind
|
|
160
|
-
is_stub = self.create_stub())
|
|
161
|
+
ext_handler = self.ext_dispatch,
|
|
162
|
+
int_handler = self.int_dispatch,
|
|
163
|
+
on_subclass_new = self.bind)
|
|
161
164
|
|
|
162
165
|
self.immutable_types.add(extended)
|
|
163
166
|
|
|
164
167
|
return extended
|
|
165
168
|
|
|
169
|
+
def function_target(self, obj): return obj
|
|
170
|
+
|
|
171
|
+
def proxy_function(self, obj):
|
|
172
|
+
return utils.wrapped_function(handler = self.ext_handler, target = obj)
|
|
173
|
+
|
|
166
174
|
def __call__(self, obj):
|
|
167
175
|
assert not isinstance(obj, BaseException)
|
|
176
|
+
assert not isinstance(obj, Proxy)
|
|
168
177
|
assert not isinstance(obj, utils.wrapped_function)
|
|
169
178
|
|
|
170
|
-
|
|
171
|
-
|
|
179
|
+
try:
|
|
180
|
+
print(f'STARTING PROXYING: {obj}')
|
|
181
|
+
if type(obj) == type:
|
|
182
|
+
if obj in self.immutable_types or issubclass(obj, tuple):
|
|
183
|
+
return obj
|
|
184
|
+
|
|
185
|
+
return self.ext_proxytype(obj)
|
|
186
|
+
|
|
187
|
+
elif type(obj) in self.immutable_types:
|
|
188
|
+
return obj
|
|
172
189
|
|
|
173
|
-
|
|
174
|
-
return utils.wrapped_function(handler = self.ext_handler, target = obj)
|
|
175
|
-
|
|
176
|
-
else:
|
|
177
|
-
proxytype = dynamic_proxytype(handler = self.ext_handler, cls = type(obj))
|
|
190
|
+
elif is_function_type(type(obj)):
|
|
178
191
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
192
|
+
return self.thread_state.dispatch(
|
|
193
|
+
obj,
|
|
194
|
+
internal = self.proxy_function(obj))
|
|
195
|
+
|
|
196
|
+
else:
|
|
197
|
+
proxytype = dynamic_proxytype(handler = self.ext_dispatch, cls = type(obj))
|
|
198
|
+
|
|
199
|
+
return utils.create_wrapped(proxytype, obj)
|
|
200
|
+
# raise Exception(f'object {obj} was not proxied as its not a extensible type and is not callable')
|
|
201
|
+
finally:
|
|
202
|
+
print(f'FINISHED PROXYING: {obj}')
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import retracesoftware.utils as utils
|
|
2
2
|
import retracesoftware.functional as functional
|
|
3
3
|
|
|
4
4
|
import types
|
|
5
5
|
|
|
6
|
+
from retracesoftware.proxy.stubfactory import StubMethodDescriptor
|
|
7
|
+
|
|
6
8
|
class Proxy:
|
|
7
9
|
__slots__ = []
|
|
8
10
|
|
|
@@ -18,6 +20,44 @@ class ExtendingProxy(Proxy):
|
|
|
18
20
|
class InternalProxy:
|
|
19
21
|
__slots__ = []
|
|
20
22
|
|
|
23
|
+
@functional.memoize_one_arg
|
|
24
|
+
def unproxy_type(cls):
|
|
25
|
+
if not issubclass(cls, Proxy):
|
|
26
|
+
return cls
|
|
27
|
+
|
|
28
|
+
# Prefer attribute on the class, not on the mappingproxy
|
|
29
|
+
target = getattr(cls, '__retrace_target_class__', None)
|
|
30
|
+
if target is not None:
|
|
31
|
+
return unproxy_type(target)
|
|
32
|
+
|
|
33
|
+
# Rebuild with unproxied bases, preserving metaclass and critical dunder attrs
|
|
34
|
+
new_bases = tuple(map(unproxy_type, cls.__bases__))
|
|
35
|
+
|
|
36
|
+
# Copy attrs, but omit implementation-managed ones
|
|
37
|
+
attrs = {}
|
|
38
|
+
classcell = None
|
|
39
|
+
for k, v in cls.__dict__.items():
|
|
40
|
+
if k in ('__dict__', '__weakref__'):
|
|
41
|
+
continue
|
|
42
|
+
if k == '__classcell__':
|
|
43
|
+
# must be passed through at class creation for zero-arg super()
|
|
44
|
+
classcell = v
|
|
45
|
+
continue
|
|
46
|
+
attrs[k] = v
|
|
47
|
+
|
|
48
|
+
# Ensure module/doc are kept (in case they weren't in __dict__)
|
|
49
|
+
attrs.setdefault('__module__', cls.__module__)
|
|
50
|
+
attrs.setdefault('__doc__', cls.__doc__)
|
|
51
|
+
|
|
52
|
+
# Use types.new_class if you want full class-creation protocol
|
|
53
|
+
def exec_body(ns):
|
|
54
|
+
ns.update(attrs)
|
|
55
|
+
if classcell is not None:
|
|
56
|
+
ns['__classcell__'] = classcell
|
|
57
|
+
|
|
58
|
+
return types.new_class(cls.__name__, new_bases, {'metaclass': type(cls)}, exec_body)
|
|
59
|
+
|
|
60
|
+
|
|
21
61
|
def superdict(cls):
|
|
22
62
|
result = {}
|
|
23
63
|
for cls in list(reversed(cls.__mro__))[1:]:
|
|
@@ -27,7 +67,9 @@ def superdict(cls):
|
|
|
27
67
|
|
|
28
68
|
def is_method_descriptor(obj):
|
|
29
69
|
return isinstance(obj, types.FunctionType) or \
|
|
30
|
-
(isinstance(obj, (types.WrapperDescriptorType,
|
|
70
|
+
(isinstance(obj, (types.WrapperDescriptorType,
|
|
71
|
+
types.MethodDescriptorType,
|
|
72
|
+
StubMethodDescriptor)) and obj.__objclass__ != object)
|
|
31
73
|
|
|
32
74
|
def proxy_method_descriptors(cls, handler):
|
|
33
75
|
for name, target in cls.__dict__.items():
|
|
@@ -86,7 +128,7 @@ def dynamic_stubtype(handler, cls):
|
|
|
86
128
|
|
|
87
129
|
assert not issubclass(cls, BaseException)
|
|
88
130
|
|
|
89
|
-
blacklist = ['__getattribute__', '__hash__', '__del__', '
|
|
131
|
+
blacklist = ['__getattribute__', '__hash__', '__del__', '__call__']
|
|
90
132
|
|
|
91
133
|
to_proxy = [m for m in methods(cls) if m not in blacklist]
|
|
92
134
|
|
|
@@ -102,26 +144,87 @@ def dynamic_stubtype(handler, cls):
|
|
|
102
144
|
spec['__call__'] = handler
|
|
103
145
|
|
|
104
146
|
spec['__retrace_target_class__'] = cls
|
|
105
|
-
spec['__class__'] = property(functional.repeatedly(cls))
|
|
106
147
|
|
|
107
|
-
|
|
148
|
+
target_type = functional.sequence(utils.unwrap, functional.typeof)
|
|
149
|
+
spec['__class__'] = property(target_type)
|
|
150
|
+
|
|
151
|
+
spec['__module__'] = cls.__module__
|
|
152
|
+
spec['__qualname__'] = cls.__name__
|
|
153
|
+
|
|
154
|
+
# name = f'retrace.proxied.{cls.__module__}.{cls.__name__}'
|
|
155
|
+
|
|
156
|
+
return type(cls.__name__, (Stub, DynamicProxy), spec)
|
|
157
|
+
|
|
158
|
+
class DescriptorProxy:
|
|
159
|
+
__slots__ = ['target', 'handler']
|
|
160
|
+
|
|
161
|
+
def __init__(self, handler, target):
|
|
162
|
+
self.handler = handler
|
|
163
|
+
self.target = target
|
|
164
|
+
|
|
165
|
+
def __get__(self, obj, cls):
|
|
166
|
+
return self.handler(self.target.__get__, obj, cls)
|
|
167
|
+
|
|
168
|
+
def __set__(self, obj, value):
|
|
169
|
+
return self.handler(self.target.__set__, obj, value)
|
|
170
|
+
|
|
171
|
+
def __delete__(self, obj):
|
|
172
|
+
return self.handler(self.target.__delete__, obj)
|
|
173
|
+
|
|
174
|
+
class ExtendingDescriptorProxy:
|
|
175
|
+
|
|
176
|
+
__slots__ = ['handler', 'proxytype', 'name']
|
|
177
|
+
|
|
178
|
+
def __init__(self, proxytype, handler, name):
|
|
179
|
+
self.proxytype = proxytype
|
|
180
|
+
self.handler = handler
|
|
181
|
+
self.name = name
|
|
182
|
+
|
|
183
|
+
def __get__(self, instance, owner):
|
|
184
|
+
inst = owner if instance is None else instance
|
|
185
|
+
getter = functional.partial(getattr, super(self.proxytype, inst))
|
|
186
|
+
return self.handler(getter, self.name)
|
|
187
|
+
|
|
188
|
+
def __set__(self, instance, value):
|
|
189
|
+
setter = functional.partial(setattr, super(self.proxytype, instance))
|
|
190
|
+
return self.handler(setter, self.name, value)
|
|
191
|
+
|
|
192
|
+
def __delete__(self, instance):
|
|
193
|
+
deleter = functional.partial(delattr, super(self.proxytype, instance))
|
|
194
|
+
return self.handler(deleter, self.name)
|
|
108
195
|
|
|
109
|
-
return type(name, (Stub, DynamicProxy), spec)
|
|
110
196
|
|
|
111
197
|
def dynamic_proxytype(handler, cls):
|
|
112
198
|
|
|
199
|
+
print(f'Creating dynamic_proxytype from {cls} {cls.__dict__}')
|
|
200
|
+
|
|
201
|
+
assert not issubclass(cls, Proxy)
|
|
113
202
|
assert not issubclass(cls, BaseException)
|
|
114
203
|
|
|
115
204
|
blacklist = ['__getattribute__', '__hash__', '__del__', '__call__']
|
|
116
205
|
|
|
117
|
-
|
|
206
|
+
spec = {}
|
|
118
207
|
|
|
119
|
-
|
|
208
|
+
for name in superdict(cls).keys():
|
|
209
|
+
if name not in blacklist:
|
|
210
|
+
value = getattr(cls, name)
|
|
211
|
+
if is_descriptor(value):
|
|
212
|
+
print(f'Adding: {name} {value} {type(value).__mro__}')
|
|
213
|
+
|
|
214
|
+
if utils.is_method_descriptor(value):
|
|
215
|
+
print(f'Adding method descriptor: {name} {value}')
|
|
216
|
+
spec[name] = utils.wrapped_function(handler = handler, target = value)
|
|
217
|
+
else:
|
|
218
|
+
spec[name] = DescriptorProxy(handler = handler, target = value)
|
|
219
|
+
|
|
220
|
+
# to_proxy = [m for m in methods(cls) if m not in blacklist]
|
|
221
|
+
|
|
222
|
+
# def wrap(target): return utils.wrapped_function(handler = handler, target = target)
|
|
120
223
|
|
|
121
|
-
spec = { name: wrap(getattr(cls, name)) for name in to_proxy }
|
|
224
|
+
# spec = { name: wrap(getattr(cls, name)) for name in to_proxy }
|
|
122
225
|
|
|
123
|
-
spec['__getattr__'] = wrap(getattr)
|
|
124
|
-
spec['__setattr__'] = wrap(setattr)
|
|
226
|
+
# spec['__getattr__'] = wrap(getattr)
|
|
227
|
+
# spec['__setattr__'] = wrap(setattr)
|
|
125
228
|
|
|
126
229
|
if utils.yields_callable_instances(cls):
|
|
127
230
|
spec['__call__'] = handler
|
|
@@ -135,6 +238,27 @@ def dynamic_proxytype(handler, cls):
|
|
|
135
238
|
|
|
136
239
|
return type(name, (utils.Wrapped, DynamicProxy), spec)
|
|
137
240
|
|
|
241
|
+
def dynamic_from_extended(cls):
|
|
242
|
+
|
|
243
|
+
base = cls.__base__
|
|
244
|
+
|
|
245
|
+
name = f'retrace.proxied.{base.__module__}.{base.__name__}'
|
|
246
|
+
|
|
247
|
+
spec = dict(cls.__dict__)
|
|
248
|
+
|
|
249
|
+
spec['__retrace_target_class__'] = base
|
|
250
|
+
|
|
251
|
+
del spec['__init_subclass__']
|
|
252
|
+
# del spec['__new__']
|
|
253
|
+
|
|
254
|
+
target_type = functional.sequence(utils.unwrap, functional.typeof)
|
|
255
|
+
spec['__class__'] = property(target_type)
|
|
256
|
+
|
|
257
|
+
print(f'dynamic_from_extended {spec}')
|
|
258
|
+
|
|
259
|
+
return type(name, (utils.Wrapped, DynamicProxy), spec)
|
|
260
|
+
|
|
261
|
+
|
|
138
262
|
def instantiable_dynamic_proxytype(handler, cls, thread_state, create_stub = False):
|
|
139
263
|
|
|
140
264
|
proxytype = dynamic_proxytype(handler = handler, cls = cls)
|
|
@@ -146,7 +270,7 @@ def instantiable_dynamic_proxytype(handler, cls, thread_state, create_stub = Fal
|
|
|
146
270
|
|
|
147
271
|
def __new__(proxytype, *args, **kwargs):
|
|
148
272
|
print(f'instantiable_dynamic_proxytype: {cls}')
|
|
149
|
-
|
|
273
|
+
|
|
150
274
|
instance = utils.create_stub_object(cls) if create_stub else cls(*args, **kwargs)
|
|
151
275
|
return utils.create_wrapped(proxytype, instance)
|
|
152
276
|
|
|
@@ -159,40 +283,53 @@ def dynamic_int_proxytype(handler, cls, bind):
|
|
|
159
283
|
proxytype.__new__ = functional.sequence(proxytype.__new__, functional.side_effect(bind))
|
|
160
284
|
return proxytype
|
|
161
285
|
|
|
162
|
-
class DescriptorProxy:
|
|
163
286
|
|
|
164
|
-
|
|
287
|
+
blacklist = ['__getattribute__', '__hash__', '__del__', '__dict__']
|
|
165
288
|
|
|
166
|
-
|
|
167
|
-
self.proxytype = proxytype
|
|
168
|
-
self.handler = handler
|
|
169
|
-
self.name = name
|
|
289
|
+
# if the type can be patched, thats better, all new instances must be of correct type
|
|
170
290
|
|
|
171
|
-
|
|
172
|
-
inst = owner if instance is None else instance
|
|
173
|
-
getter = functional.partial(getattr, super(self.proxytype, inst))
|
|
174
|
-
return self.handler(getter, self.name)
|
|
291
|
+
# def make_extensible(thread_state, proxy_method_descriptor, cls):
|
|
175
292
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
293
|
+
# @functional.memoize_one_arg
|
|
294
|
+
# def proxy_subclass(subclass):
|
|
295
|
+
# if '__retrace_target_type__' in subclass.__dict__:
|
|
296
|
+
# return subclass
|
|
297
|
+
|
|
298
|
+
# attrs = {k: proxy_method_descriptor(v) for k, v in subclass.__dict__.items() if is_method_descriptor(v) }
|
|
179
299
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
300
|
+
# # Ensure module/doc are kept (in case they weren't in __dict__)
|
|
301
|
+
# attrs.setdefault('__module__', subclass.__module__)
|
|
302
|
+
# attrs.setdefault('__doc__', subclass.__doc__)
|
|
303
|
+
# attrs['__retrace_target_type__'] = subclass
|
|
183
304
|
|
|
305
|
+
# return type(subclass.__name__, (subclass,), attrs)
|
|
184
306
|
|
|
185
|
-
|
|
307
|
+
# orig__new__ = cls.__new__
|
|
186
308
|
|
|
187
|
-
#
|
|
309
|
+
# def proxied__new__(subclass, *args, **kwargs):
|
|
310
|
+
# nonlocal orig__new__
|
|
311
|
+
# return orig__new__(proxy_subclass(subclass), *args, **kwargs)
|
|
312
|
+
|
|
313
|
+
# def unproxied__new__(subclass, *args, **kwargs):
|
|
314
|
+
# return unproxy_type(subclass)(*args, **kwargs)
|
|
315
|
+
|
|
316
|
+
# # Dispatch which constructor to use based on your thread_state policy
|
|
317
|
+
# cls.__new__ = thread_state.dispatch(unproxied__new__, internal = proxied__new__)
|
|
318
|
+
|
|
319
|
+
def create_unproxied_type(cls):
|
|
320
|
+
|
|
321
|
+
def unproxy_type(cls):
|
|
322
|
+
return cls.__dict__.get('__retrace_unproxied__', cls)
|
|
323
|
+
|
|
324
|
+
return type(cls.__name__, tuple(map(unproxy_type, cls.__bases__)), dict(cls.__dict__))
|
|
188
325
|
|
|
189
|
-
def extending_proxytype(cls, thread_state, ext_handler, int_handler, on_subclass_new
|
|
326
|
+
def extending_proxytype(cls, base, thread_state, ext_handler, int_handler, on_subclass_new):
|
|
190
327
|
|
|
191
328
|
assert not issubclass(cls, BaseException)
|
|
192
329
|
|
|
193
330
|
def init_subclass(subclass, **kwargs):
|
|
194
|
-
print(f'In init_subclass: {subclass} {kwargs}')
|
|
195
|
-
|
|
331
|
+
# print(f'In init_subclass: {subclass} {kwargs}')
|
|
332
|
+
subclass.__retrace_unproxied__ = create_unproxied_type(subclass)
|
|
196
333
|
|
|
197
334
|
proxy_method_descriptors(cls = subclass, handler = int_handler)
|
|
198
335
|
|
|
@@ -200,7 +337,10 @@ def extending_proxytype(cls, thread_state, ext_handler, int_handler, on_subclass
|
|
|
200
337
|
subclass.__new__ = functional.sequence(subclass.__new__, functional.side_effect(on_subclass_new))
|
|
201
338
|
subclass.__bases__ = subclass.__bases__ + (InternalProxy,)
|
|
202
339
|
|
|
203
|
-
slots = { "__slots__": (),
|
|
340
|
+
slots = { "__slots__": (),
|
|
341
|
+
"__retrace_unproxied__": cls,
|
|
342
|
+
"__module__": cls.__module__,
|
|
343
|
+
"__init_subclass__": init_subclass }
|
|
204
344
|
|
|
205
345
|
def wrap(target): return utils.wrapped_function(handler = ext_handler, target = target)
|
|
206
346
|
|
|
@@ -213,79 +353,67 @@ def extending_proxytype(cls, thread_state, ext_handler, int_handler, on_subclass
|
|
|
213
353
|
elif is_descriptor(value):
|
|
214
354
|
descriptors.append(name)
|
|
215
355
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
extended = type(name, (cls, ExtendingProxy), slots)
|
|
356
|
+
extended = type(cls.__name__, (base, ExtendingProxy), slots)
|
|
219
357
|
|
|
220
358
|
for name in descriptors:
|
|
221
|
-
proxy =
|
|
359
|
+
proxy = ExtendingDescriptorProxy(handler = ext_handler, name = name, proxytype = extended)
|
|
222
360
|
setattr(extended, name, proxy)
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
# utils.sigtrap(None)
|
|
229
|
-
return instance
|
|
230
|
-
|
|
231
|
-
extended.__new__ = thread_state.dispatch(cls.__new__, internal = __new__, external = __new__)
|
|
232
|
-
|
|
233
|
-
# extended.__retrace_unproxied__ = cls
|
|
361
|
+
|
|
362
|
+
def unproxied__new__(subclass, *args, **kwargs):
|
|
363
|
+
return subclass.__retrace_unproxied__(*args, **kwargs)
|
|
364
|
+
|
|
365
|
+
extended.__new__ = thread_state.dispatch(unproxied__new__, internal = base.__new__)
|
|
234
366
|
|
|
235
367
|
return extended
|
|
236
368
|
|
|
237
369
|
|
|
238
|
-
def stubtype(cls, result, thread_state, handler):
|
|
370
|
+
# def stubtype(cls, result, thread_state, handler):
|
|
239
371
|
|
|
240
|
-
|
|
372
|
+
# name = f'retrace.stub.{cls.__module__}.{cls.__name__}'
|
|
241
373
|
|
|
242
|
-
|
|
374
|
+
# slots = {}
|
|
243
375
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
376
|
+
# def wrap(name):
|
|
377
|
+
# return utils.wrapped_function(
|
|
378
|
+
# handler = handler,
|
|
379
|
+
# target = StubMethodDescriptor(name = name, result = result))
|
|
248
380
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
381
|
+
# for name,value in superdict(cls).items():
|
|
382
|
+
# if name not in blacklist:
|
|
383
|
+
# if is_method_descriptor(value):
|
|
384
|
+
# slots[name] = wrap(name)
|
|
385
|
+
# elif is_descriptor(value):
|
|
386
|
+
# slots[name] = DescriptorStub(handler = handler, name = name)
|
|
255
387
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
388
|
+
# def disabled__new__(subcls, *args, **kwargs):
|
|
389
|
+
# instance = cls.__new__(subcls.__retrace_unproxied__, *args, **kwargs)
|
|
390
|
+
# instance.__init__(*args, **kwargs)
|
|
391
|
+
# return instance
|
|
260
392
|
|
|
261
|
-
|
|
393
|
+
# stub = type(name, (Stub,), slots)
|
|
262
394
|
|
|
263
|
-
|
|
395
|
+
# stub.__new__ = thread_state.dispatch(disabled__new__, internal = stub.__new__, external = stub.__new__)
|
|
264
396
|
|
|
265
|
-
|
|
397
|
+
# stub.__retrace_unproxied__ = cls
|
|
398
|
+
|
|
399
|
+
# return stub
|
|
266
400
|
|
|
267
|
-
return stub
|
|
268
401
|
|
|
269
|
-
def create_unproxied_type(cls):
|
|
270
|
-
name = f'{cls.__module__}.{cls.__name__}'
|
|
271
402
|
|
|
272
|
-
def unproxy_type(cls):
|
|
273
|
-
return cls.__retrace_unproxied__ if issubclass(cls, ExtendingProxy) else cls
|
|
274
403
|
|
|
275
|
-
return type(name, tuple(map(unproxy_type, cls.__bases__)), dict(cls.__dict__))
|
|
276
404
|
|
|
277
|
-
def make_extensible(cls, handler, on_new):
|
|
405
|
+
# def make_extensible(cls, handler, on_new):
|
|
278
406
|
|
|
279
|
-
|
|
407
|
+
# cls.__retrace_unproxied__ = cls.__base__
|
|
280
408
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
409
|
+
# def init_subclass(*args, **kwargs):
|
|
410
|
+
# print(f'In init_subclass: {args} {kwargs}')
|
|
411
|
+
# # subclass.__retrace_unproxied__ = create_unproxied_type(subclass)
|
|
284
412
|
|
|
285
|
-
|
|
413
|
+
# # proxy_method_descriptors(cls = subclass, handler = handler)
|
|
286
414
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
415
|
+
# # if not issubclass(subclass, InternalProxy):
|
|
416
|
+
# # cls.__new__ = functional.compose(cls.__new__, functional.side_effect(on_new))
|
|
417
|
+
# # cls.__bases__ = cls.__bases__ + (InternalProxy,)
|
|
290
418
|
|
|
291
|
-
|
|
419
|
+
# cls.__init_subclass__ = init_subclass
|