retracesoftware-proxy 0.1.1__py3-none-any.whl → 0.1.3__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.
@@ -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 adapter_pair1
4
+ from retracesoftware.proxy.gateway import adapter_pair
5
5
  from types import SimpleNamespace
6
- from retracesoftware.proxy.proxytype import ExtendingProxy
6
+ from retracesoftware.proxy.proxytype import *
7
+ from retracesoftware.proxy.stubfactory import Stub
8
+ import sys
9
+ import gc
7
10
 
8
- from retracesoftware.proxy.proxytype import extending_proxytype, make_extensible, dynamic_proxytype, dynamic_int_proxytype, instantiable_dynamic_proxytype
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
- create,
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 wrap_int_to_ext(self, obj): return obj
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
- proxytype = self.int_proxytype,
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
- proxytype = self.ext_proxytype,
80
- proxy = proxyfactory(self.ext_proxytype),
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 = adapter_pair1(int_spec, ext_spec)
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 = 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)
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,80 @@ class ProxySystem:
134
118
 
135
119
  def int_proxytype(self, cls):
136
120
  return dynamic_int_proxytype(
137
- handler = self.int_handler,
121
+ handler = self.int_dispatch,
138
122
  cls = cls,
139
123
  bind = self.bind)
140
124
 
125
+ def dynamic_ext_proxytype(self, cls):
126
+
127
+ proxytype = dynamic_proxytype(
128
+ handler = self.ext_dispatch,
129
+ cls = cls)
130
+ if self.on_proxytype:
131
+ self.on_proxytype(proxytype)
132
+
133
+ return proxytype
134
+
135
+ # resolved = resolve(cls)
136
+ # if isinstance(resolved, ExtendingProxy):
137
+ # return dynamic_from_extended(resolved)
138
+ # elif isinstance(resolved, DynamicProxy):
139
+ # return resolved
140
+ # else:
141
+ # return dynamic_proxytype(handler = self.ext_dispatch, cls = cls)
142
+
141
143
  def ext_proxytype(self, cls):
142
144
  assert isinstance(cls, type)
143
145
  if utils.is_extendable(cls):
144
146
  return self.extend_type(cls)
145
147
  else:
146
148
  return instantiable_dynamic_proxytype(
147
- handler = self.ext_handler,
149
+ handler = self.ext_dispatch,
148
150
  cls = cls,
149
151
  thread_state = self.thread_state,
150
152
  create_stub = self.create_stub())
151
153
 
152
- def extend_type(self, base):
154
+ def extend_type(self, cls):
153
155
 
154
156
  extended = extending_proxytype(
155
- cls = base,
157
+ cls = cls,
158
+ base = Stub if self.create_stub() else cls,
156
159
  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())
160
+ ext_handler = self.ext_dispatch,
161
+ int_handler = self.int_dispatch,
162
+ on_subclass_new = self.bind)
161
163
 
162
164
  self.immutable_types.add(extended)
163
165
 
164
166
  return extended
165
167
 
168
+ def function_target(self, obj): return obj
169
+
170
+ def proxy_function(self, obj):
171
+ return utils.wrapped_function(handler = self.ext_handler, target = obj)
172
+
166
173
  def __call__(self, obj):
167
174
  assert not isinstance(obj, BaseException)
175
+ assert not isinstance(obj, Proxy)
168
176
  assert not isinstance(obj, utils.wrapped_function)
169
177
 
170
178
  if type(obj) == type:
179
+ if obj in self.immutable_types or issubclass(obj, tuple):
180
+ return obj
181
+
171
182
  return self.ext_proxytype(obj)
172
183
 
173
- elif type(obj) == types.BuiltinFunctionType:
174
- return utils.wrapped_function(handler = self.ext_handler, target = obj)
184
+ elif type(obj) in self.immutable_types:
185
+ return obj
186
+
187
+ elif is_function_type(type(obj)):
188
+
189
+ return self.thread_state.dispatch(
190
+ obj,
191
+ internal = self.proxy_function(obj))
175
192
 
176
193
  else:
177
- proxytype = dynamic_proxytype(handler = self.ext_handler, cls = type(obj))
194
+ proxytype = dynamic_proxytype(handler = self.ext_dispatch, cls = type(obj))
178
195
 
179
196
  return utils.create_wrapped(proxytype, obj)
180
197
  # raise Exception(f'object {obj} was not proxied as its not a extensible type and is not callable')
181
-
@@ -1,8 +1,10 @@
1
- import retracesoftware_utils as utils
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, types.MethodDescriptorType)) and obj.__objclass__ != object)
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__', '__init__', '__call__']
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,82 @@ 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
- name = f'retrace.proxied.{cls.__module__}.{cls.__name__}'
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
+ assert not issubclass(cls, Proxy)
113
200
  assert not issubclass(cls, BaseException)
114
201
 
115
202
  blacklist = ['__getattribute__', '__hash__', '__del__', '__call__']
116
203
 
117
- to_proxy = [m for m in methods(cls) if m not in blacklist]
204
+ spec = {}
118
205
 
119
- def wrap(target): return utils.wrapped_function(handler = handler, target = target)
206
+ for name in superdict(cls).keys():
207
+ if name not in blacklist:
208
+ value = getattr(cls, name)
209
+ if is_descriptor(value):
210
+ if utils.is_method_descriptor(value):
211
+ spec[name] = utils.wrapped_function(handler = handler, target = value)
212
+ else:
213
+ spec[name] = DescriptorProxy(handler = handler, target = value)
214
+
215
+ # to_proxy = [m for m in methods(cls) if m not in blacklist]
216
+
217
+ # def wrap(target): return utils.wrapped_function(handler = handler, target = target)
120
218
 
121
- spec = { name: wrap(getattr(cls, name)) for name in to_proxy }
219
+ # spec = { name: wrap(getattr(cls, name)) for name in to_proxy }
122
220
 
123
- spec['__getattr__'] = wrap(getattr)
124
- spec['__setattr__'] = wrap(setattr)
221
+ # spec['__getattr__'] = wrap(getattr)
222
+ # spec['__setattr__'] = wrap(setattr)
125
223
 
126
224
  if utils.yields_callable_instances(cls):
127
225
  spec['__call__'] = handler
@@ -135,6 +233,25 @@ def dynamic_proxytype(handler, cls):
135
233
 
136
234
  return type(name, (utils.Wrapped, DynamicProxy), spec)
137
235
 
236
+ def dynamic_from_extended(cls):
237
+
238
+ base = cls.__base__
239
+
240
+ name = f'retrace.proxied.{base.__module__}.{base.__name__}'
241
+
242
+ spec = dict(cls.__dict__)
243
+
244
+ spec['__retrace_target_class__'] = base
245
+
246
+ del spec['__init_subclass__']
247
+ # del spec['__new__']
248
+
249
+ target_type = functional.sequence(utils.unwrap, functional.typeof)
250
+ spec['__class__'] = property(target_type)
251
+
252
+ return type(name, (utils.Wrapped, DynamicProxy), spec)
253
+
254
+
138
255
  def instantiable_dynamic_proxytype(handler, cls, thread_state, create_stub = False):
139
256
 
140
257
  proxytype = dynamic_proxytype(handler = handler, cls = cls)
@@ -145,8 +262,6 @@ def instantiable_dynamic_proxytype(handler, cls, thread_state, create_stub = Fal
145
262
  return instance
146
263
 
147
264
  def __new__(proxytype, *args, **kwargs):
148
- print(f'instantiable_dynamic_proxytype: {cls}')
149
-
150
265
  instance = utils.create_stub_object(cls) if create_stub else cls(*args, **kwargs)
151
266
  return utils.create_wrapped(proxytype, instance)
152
267
 
@@ -159,40 +274,58 @@ def dynamic_int_proxytype(handler, cls, bind):
159
274
  proxytype.__new__ = functional.sequence(proxytype.__new__, functional.side_effect(bind))
160
275
  return proxytype
161
276
 
162
- class DescriptorProxy:
163
277
 
164
- __slots__ = ['handler', 'proxytype', 'name']
278
+ blacklist = ['__getattribute__', '__hash__', '__del__', '__dict__']
165
279
 
166
- def __init__(self, proxytype, handler, name):
167
- self.proxytype = proxytype
168
- self.handler = handler
169
- self.name = name
280
+ # if the type can be patched, thats better, all new instances must be of correct type
170
281
 
171
- def __get__(self, instance, owner):
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)
282
+ # def make_extensible(thread_state, proxy_method_descriptor, cls):
175
283
 
176
- def __set__(self, instance, value):
177
- setter = functional.partial(setattr, super(self.proxytype, instance))
178
- return self.handler(setter, self.name, value)
284
+ # @functional.memoize_one_arg
285
+ # def proxy_subclass(subclass):
286
+ # if '__retrace_target_type__' in subclass.__dict__:
287
+ # return subclass
288
+
289
+ # attrs = {k: proxy_method_descriptor(v) for k, v in subclass.__dict__.items() if is_method_descriptor(v) }
179
290
 
180
- def __delete__(self, instance):
181
- deleter = functional.partial(delattr, super(self.proxytype, instance))
182
- return self.handler(deleter, self.name)
291
+ # # Ensure module/doc are kept (in case they weren't in __dict__)
292
+ # attrs.setdefault('__module__', subclass.__module__)
293
+ # attrs.setdefault('__doc__', subclass.__doc__)
294
+ # attrs['__retrace_target_type__'] = subclass
183
295
 
296
+ # return type(subclass.__name__, (subclass,), attrs)
184
297
 
185
- blacklist = ['__getattribute__', '__hash__', '__del__', '__dict__']
298
+ # orig__new__ = cls.__new__
186
299
 
187
- # if the type can be patched, thats better, all new instances must be of correct type
300
+ # def proxied__new__(subclass, *args, **kwargs):
301
+ # nonlocal orig__new__
302
+ # return orig__new__(proxy_subclass(subclass), *args, **kwargs)
303
+
304
+ # def unproxied__new__(subclass, *args, **kwargs):
305
+ # return unproxy_type(subclass)(*args, **kwargs)
306
+
307
+ # # Dispatch which constructor to use based on your thread_state policy
308
+ # cls.__new__ = thread_state.dispatch(unproxied__new__, internal = proxied__new__)
309
+
310
+ def create_unproxied_type(cls):
311
+ def unproxy_type(cls):
312
+ return cls.__dict__.get('__retrace_unproxied__', cls)
188
313
 
189
- def extending_proxytype(cls, thread_state, ext_handler, int_handler, on_subclass_new, is_stub = False):
314
+ bases = tuple(map(unproxy_type, cls.__bases__))
315
+ slots = dict(cls.__dict__)
316
+ del slots['__init_subclass__']
317
+ return type(cls.__name__, tuple(bases), slots)
190
318
 
319
+ def extending_proxytype(cls, base, thread_state, ext_handler, int_handler, on_subclass_new):
320
+
321
+ # assert cls is base
191
322
  assert not issubclass(cls, BaseException)
323
+ assert not issubclass(cls, ExtendingProxy)
192
324
 
193
325
  def init_subclass(subclass, **kwargs):
194
326
  print(f'In init_subclass: {subclass} {kwargs}')
195
- # subclass.__retrace_unproxied__ = create_unproxied_type(subclass)
327
+ unproxied = create_unproxied_type(subclass)
328
+ subclass.__retrace_unproxied__ = unproxied
196
329
 
197
330
  proxy_method_descriptors(cls = subclass, handler = int_handler)
198
331
 
@@ -200,7 +333,12 @@ def extending_proxytype(cls, thread_state, ext_handler, int_handler, on_subclass
200
333
  subclass.__new__ = functional.sequence(subclass.__new__, functional.side_effect(on_subclass_new))
201
334
  subclass.__bases__ = subclass.__bases__ + (InternalProxy,)
202
335
 
203
- slots = { "__slots__": (), "__init_subclass__": init_subclass }
336
+ assert not issubclass(subclass.__retrace_unproxied__, ExtendingProxy)
337
+
338
+ slots = { "__slots__": (),
339
+ "__retrace_unproxied__": cls,
340
+ "__module__": cls.__module__,
341
+ "__init_subclass__": init_subclass }
204
342
 
205
343
  def wrap(target): return utils.wrapped_function(handler = ext_handler, target = target)
206
344
 
@@ -213,79 +351,22 @@ def extending_proxytype(cls, thread_state, ext_handler, int_handler, on_subclass
213
351
  elif is_descriptor(value):
214
352
  descriptors.append(name)
215
353
 
216
- name = f'retrace.extended.{cls.__module__}.{cls.__name__}'
354
+ slots['__retrace_unproxied__'] = cls
217
355
 
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 = DescriptorProxy(handler = ext_handler, name = name, proxytype = extended)
359
+ proxy = ExtendingDescriptorProxy(handler = ext_handler, name = name, proxytype = extended)
222
360
  setattr(extended, name, proxy)
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__)
223
366
 
224
- if is_stub:
225
- def __new__(cls, *args, **kwargs):
226
- instance = utils.create_stub_object(cls)
227
- # print(instance is None)
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
367
+ assert not issubclass(extended.__retrace_unproxied__, ExtendingProxy)
368
+ assert extended.__dict__['__retrace_unproxied__'] is extended.__retrace_unproxied__
369
+ print(f'FOO: {extended} {id(extended)} {id(extended.__retrace_unproxied__)}')
370
+ # breakpoint()
234
371
 
235
372
  return extended
236
-
237
-
238
- def stubtype(cls, result, thread_state, handler):
239
-
240
- name = f'retrace.stub.{cls.__module__}.{cls.__name__}'
241
-
242
- slots = {}
243
-
244
- def wrap(name):
245
- return utils.wrapped_function(
246
- handler = handler,
247
- target = StubMethodDescriptor(name = name, result = result))
248
-
249
- for name,value in superdict(cls).items():
250
- if name not in blacklist:
251
- if is_method_descriptor(value):
252
- slots[name] = wrap(name)
253
- elif is_descriptor(value):
254
- slots[name] = DescriptorStub(handler = handler, name = name)
255
-
256
- def disabled__new__(subcls, *args, **kwargs):
257
- instance = cls.__new__(subcls.__retrace_unproxied__, *args, **kwargs)
258
- instance.__init__(*args, **kwargs)
259
- return instance
260
-
261
- stub = type(name, (Stub,), slots)
262
-
263
- stub.__new__ = thread_state.dispatch(disabled__new__, internal = stub.__new__, external = stub.__new__)
264
-
265
- stub.__retrace_unproxied__ = cls
266
-
267
- return stub
268
-
269
- def create_unproxied_type(cls):
270
- name = f'{cls.__module__}.{cls.__name__}'
271
-
272
- def unproxy_type(cls):
273
- return cls.__retrace_unproxied__ if issubclass(cls, ExtendingProxy) else cls
274
-
275
- return type(name, tuple(map(unproxy_type, cls.__bases__)), dict(cls.__dict__))
276
-
277
- def make_extensible(cls, handler, on_new):
278
-
279
- cls.__retrace_unproxied__ = cls.__base__
280
-
281
- def init_subclass(*args, **kwargs):
282
- print(f'In init_subclass: {args} {kwargs}')
283
- # subclass.__retrace_unproxied__ = create_unproxied_type(subclass)
284
-
285
- # proxy_method_descriptors(cls = subclass, handler = handler)
286
-
287
- # if not issubclass(subclass, InternalProxy):
288
- # cls.__new__ = functional.compose(cls.__new__, functional.side_effect(on_new))
289
- # cls.__bases__ = cls.__bases__ + (InternalProxy,)
290
-
291
- cls.__init_subclass__ = init_subclass