retracesoftware-proxy 0.1.8__py3-none-any.whl → 0.1.9__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.
@@ -182,9 +182,11 @@
182
182
  },
183
183
 
184
184
  "importlib._bootstrap": {
185
+ "comment": {
185
186
  "with_state": {
186
187
  "bootstrap": ["_load_unlocked", "_find_spec"]
187
188
  }
189
+ }
188
190
  },
189
191
 
190
192
  "encodings": {
@@ -275,7 +275,7 @@ class Patcher:
275
275
 
276
276
  @patch
277
277
  def patch_start_new_thread(self, value):
278
- def start_new_thread(self, function, *args):
278
+ def start_new_thread(function, *args):
279
279
  # synchronized, replay shoudl yield correct number
280
280
  thread_id = self.thread_counter()
281
281
 
@@ -474,18 +474,19 @@ class Patcher:
474
474
 
475
475
  def __call__(self, module):
476
476
 
477
- if not hasattr(module, '__retrace__'):
478
- configs = list(self.configs(module))
479
-
480
- if len(configs) > 0:
481
- if len(configs) > 1:
482
- raise Exception(f'TODO')
483
- else:
484
- module.__retrace__ = None
485
- try:
486
- self.patch_module_with_name(configs[0], module)
487
- except Exception as error:
488
- raise Exception(f'Error patching module: {configs[0]}') from error
477
+ if self.thread_state.value == 'internal' and not hasattr(module, '__retrace__'):
478
+ with self.thread_state.select('bootstrap'):
479
+ configs = list(self.configs(module))
480
+
481
+ if len(configs) > 0:
482
+ if len(configs) > 1:
483
+ raise Exception(f'TODO')
484
+ else:
485
+ module.__retrace__ = None
486
+ try:
487
+ self.patch_module_with_name(configs[0], module)
488
+ except Exception as error:
489
+ raise Exception(f'Error patching module: {configs[0]}') from error
489
490
 
490
491
  return module
491
492
 
@@ -13,11 +13,34 @@ def format_kwargs(kwargs):
13
13
  return tuple(result)
14
14
 
15
15
  class Tracer:
16
+
16
17
  def __init__(self, config, writer):
17
18
  self.config = config
18
19
  serialize = functional.walker(self.serialize)
19
20
  self.writer = functional.mapargs(transform = serialize, function = writer)
20
21
 
22
+ def systrace(self, frame, event, arg):
23
+ try:
24
+ if event in ['line', 'call']:
25
+ print(f'In systrace: {event} {frame.f_code.co_filename}:{frame.f_lineno}')
26
+ self.writer(event, frame.f_code.co_filename, frame.f_code.co_name, frame.f_lineno)
27
+
28
+ elif event == 'return':
29
+ print(f'In systrace: {event}')
30
+ self.writer(event)
31
+ # self.writer(event, self.serialize(arg))
32
+
33
+ elif event == 'exception':
34
+ print(f'In systrace: {event}')
35
+ self.writer(event)
36
+ else:
37
+ print(f'In systrace: {event}')
38
+
39
+ return self.systrace
40
+ except:
41
+ print(f'systrace RAISED ERROR!')
42
+ raise
43
+
21
44
  def serialize(self, obj):
22
45
  try:
23
46
  if obj is None: return None
@@ -56,6 +79,9 @@ class Tracer:
56
79
  if name in self.config:
57
80
  self.writer(name, message)
58
81
 
82
+ def checkpoint(self, obj):
83
+ self.writer(obj)
84
+
59
85
  def stacktrace(self):
60
86
  self.writer('stacktrace', utils.stacktrace())
61
87
 
@@ -63,8 +89,11 @@ class Tracer:
63
89
  if name in self.config:
64
90
  if name.endswith('.call'):
65
91
  def write_call(*args, **kwargs):
66
- # self.stacktrace()
67
- self.writer(name, args[0].__name__, args[1:], kwargs)
92
+ self.stacktrace()
93
+ if len(args) > 0:
94
+ self.writer(name, args[0].__name__, args[1:], kwargs)
95
+ else:
96
+ breakpoint()
68
97
 
69
98
  return functional.firstof(write_call, func) if func else write_call
70
99
 
@@ -36,13 +36,14 @@ def resolve(obj):
36
36
  def is_function_type(cls):
37
37
  return cls in [types.BuiltinFunctionType, types.FunctionType]
38
38
 
39
+ def is_instance_method(obj):
40
+ return isinstance(obj, types.MethodDescriptorType) or isinstance(obj, types.FunctionType)
41
+
39
42
  class ProxySystem:
40
43
 
41
44
  def bind(self, obj): pass
42
45
 
43
- def wrap_int_to_ext(self, obj):
44
- return obj
45
- # return functional.sequence(functional.side_effect(functional.repeatedly(gc.collect)), obj)
46
+ def wrap_int_to_ext(self, obj): return obj
46
47
 
47
48
  def wrap_ext_to_int(self, obj): return obj
48
49
 
@@ -58,6 +59,9 @@ class ProxySystem:
58
59
  # def stacktrace(self):
59
60
  # self.tracer.stacktrace()
60
61
 
62
+ def set_thread_id(self, id):
63
+ utils.set_thread_id(id)
64
+
61
65
  def __init__(self, thread_state, immutable_types, tracer):
62
66
 
63
67
  self.thread_state = thread_state
@@ -67,7 +71,7 @@ class ProxySystem:
67
71
  self.on_proxytype = None
68
72
 
69
73
  def is_immutable_type(cls):
70
- return issubclass(cls, tuple(immutable_types))
74
+ return cls is object or issubclass(cls, tuple(immutable_types))
71
75
 
72
76
  is_immutable = functional.sequence(functional.typeof, functional.memoize_one_arg(is_immutable_type))
73
77
 
@@ -84,7 +88,7 @@ class ProxySystem:
84
88
 
85
89
  ext_spec = SimpleNamespace(
86
90
  apply = thread_state.wrap('external', functional.apply),
87
- proxy = proxyfactory(thread_state.wrap('disabled', self.dynamic_ext_proxytype)),
91
+ proxy = proxyfactory(thread_state.wrap('disabled', self.ext_proxytype)),
88
92
  on_call = tracer('proxy.ext.call'),
89
93
  on_result = self.on_ext_result,
90
94
  on_error = self.on_ext_error,
@@ -102,6 +106,11 @@ class ProxySystem:
102
106
  self.ext_dispatch = gateway('proxy.int.disabled.event', internal = self.ext_handler)
103
107
  self.int_dispatch = gateway('proxy.ext.disabled.event', external = self.int_handler)
104
108
 
109
+ if 'systrace' in tracer.config:
110
+ func = thread_state.wrap(desired_state = 'disabled', function = tracer.systrace)
111
+ func = self.thread_state.dispatch(lambda *args: None, internal = func)
112
+ sys.settrace(func)
113
+
105
114
  def new_child_path(self, path):
106
115
  return path.parent / f'fork-{self.fork_counter}' / path.name
107
116
 
@@ -117,9 +126,12 @@ class ProxySystem:
117
126
  self.thread_state.value = self.saved_thread_state
118
127
  self.fork_counter += 1
119
128
 
120
- def create_stub(self): return False
129
+ # def create_stub(self): return False
121
130
 
122
131
  def int_proxytype(self, cls):
132
+ if cls is object:
133
+ breakpoint()
134
+
123
135
  proxytype = dynamic_int_proxytype(
124
136
  handler = self.int_dispatch,
125
137
  cls = cls,
@@ -128,64 +140,64 @@ class ProxySystem:
128
140
  if self.on_proxytype: self.on_proxytype(proxytype)
129
141
  return proxytype
130
142
 
131
-
132
- def dynamic_ext_proxytype(self, cls):
143
+ def ext_proxytype(self, cls):
144
+ if cls is object:
145
+ breakpoint()
133
146
 
134
147
  proxytype = dynamic_proxytype(handler = self.ext_dispatch, cls = cls)
135
148
 
136
149
  if self.on_proxytype: self.on_proxytype(proxytype)
137
150
 
138
151
  return proxytype
152
+
153
+ def function_target(self, obj): return obj
154
+
155
+ def proxy_function(self, obj):
156
+ return utils.wrapped_function(handler = self.ext_handler, target = obj)
139
157
 
140
- # resolved = resolve(cls)
141
- # if isinstance(resolved, ExtendingProxy):
142
- # return dynamic_from_extended(resolved)
143
- # elif isinstance(resolved, DynamicProxy):
144
- # return resolved
145
- # else:
146
- # return dynamic_proxytype(handler = self.ext_dispatch, cls = cls)
158
+ def patchtype(self, cls):
159
+ if cls in self.immutable_types or issubclass(cls, tuple):
160
+ return cls
161
+
162
+ def wrap(func):
163
+ return self.thread_state.dispatch(func, internal = self.proxy_function(func))
164
+
165
+ def wrap_new(func):
166
+ proxied = self.proxy_function(func)
167
+
168
+ def new(cls, *args, **kwargs):
169
+ instance = proxied(cls, *args, **kwargs)
170
+ instance.__init__(*args, **kwargs)
171
+ return instance
172
+
173
+ return self.thread_state.dispatch(func, internal = new)
147
174
 
148
- def ext_proxytype(self, cls):
149
- assert isinstance(cls, type)
150
175
  if utils.is_extendable(cls):
151
- proxytype = self.extend_type(cls)
152
- if self.on_proxytype: self.on_proxytype(proxytype)
153
- return proxytype
154
- else:
155
- new = functional.droparg(self.proxy_function(cls))
156
- return type(cls.__name__, (object,), {'__module__': cls.__module__, '__new__': new})
176
+ slots = {'__module__': cls.__module__, '__slots__': []}
157
177
 
158
- def basetype(self, cls):
159
- return cls
160
-
161
- def extend_type(self, cls):
162
- extended = extending_proxytype(
163
- cls = cls,
164
- base = self.basetype(cls),
165
- thread_state = self.thread_state,
166
- ext_handler = self.ext_dispatch,
167
- int_handler = self.int_dispatch,
168
- on_subclass_new = self.bind)
169
-
170
- self.immutable_types.add(extended)
178
+ for name, value in superdict(cls).items():
179
+ if callable(value) and not is_instance_method(value):
180
+ slots[name] = wrap_new(value) if name == '__new__' else wrap(value)
171
181
 
172
- return extended
182
+ return type(cls.__name__, (cls,), slots)
173
183
 
174
- def function_target(self, obj): return obj
184
+ elif not utils.is_immutable(cls):
185
+ def update(name, f):
186
+ setattr(cls, name, f(getattr(cls, name)))
187
+
188
+ for name, value in superdict(cls).items():
189
+ if callable(value) and not is_instance_method(value):
190
+ update(name, wrap_new if name == '__new__' else wrap)
191
+ else:
192
+ return wrap(cls)
175
193
 
176
- def proxy_function(self, obj):
177
- return utils.wrapped_function(handler = self.ext_handler, target = obj)
178
-
179
194
  def __call__(self, obj):
180
195
  assert not isinstance(obj, BaseException)
181
196
  assert not isinstance(obj, Proxy)
182
197
  assert not isinstance(obj, utils.wrapped_function)
183
198
 
184
- if type(obj) == type:
185
- if obj in self.immutable_types or issubclass(obj, tuple):
186
- return obj
187
-
188
- return self.ext_proxytype(obj)
199
+ if type(obj) == type:
200
+ return self.patchtype(obj)
189
201
 
190
202
  elif type(obj) in self.immutable_types:
191
203
  return obj
@@ -163,7 +163,11 @@ class DescriptorProxy:
163
163
  self.target = target
164
164
 
165
165
  def __get__(self, obj, cls):
166
- return self.handler(self.target.__get__, obj, cls)
166
+ try:
167
+ return self.handler(self.target.__get__, obj, cls)
168
+ except:
169
+ print(f'error calling __get__')
170
+ raise
167
171
 
168
172
  def __set__(self, obj, value):
169
173
  return self.handler(self.target.__set__, obj, value)
@@ -171,28 +175,28 @@ class DescriptorProxy:
171
175
  def __delete__(self, obj):
172
176
  return self.handler(self.target.__delete__, obj)
173
177
 
174
- class ExtendingDescriptorProxy:
178
+ # class ExtendingDescriptorProxy:
175
179
 
176
- __slots__ = ['handler', 'proxytype', 'name']
180
+ # __slots__ = ['handler', 'proxytype', 'name']
177
181
 
178
- def __init__(self, proxytype, handler, name):
179
- self.proxytype = proxytype
180
- self.handler = handler
181
- self.name = name
182
+ # def __init__(self, proxytype, handler, name):
183
+ # self.proxytype = proxytype
184
+ # self.handler = handler
185
+ # self.name = name
182
186
 
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
+ # def __get__(self, instance, owner):
188
+ # inst = owner if instance is None else instance
189
+ # getter = functional.partial(getattr, super(self.proxytype, inst))
190
+ # return self.handler(getter, self.name)
187
191
 
188
- def __set__(self, instance, value):
189
- breakpoint()
190
- setter = functional.partial(setattr, super(self.proxytype, instance))
191
- return self.handler(setter, self.name, value)
192
+ # def __set__(self, instance, value):
193
+ # breakpoint()
194
+ # setter = functional.partial(setattr, super(self.proxytype, instance))
195
+ # return self.handler(setter, self.name, value)
192
196
 
193
- def __delete__(self, instance):
194
- deleter = functional.partial(delattr, super(self.proxytype, instance))
195
- return self.handler(deleter, self.name)
197
+ # def __delete__(self, instance):
198
+ # deleter = functional.partial(delattr, super(self.proxytype, instance))
199
+ # return self.handler(deleter, self.name)
196
200
 
197
201
 
198
202
  def dynamic_proxytype(handler, cls):
@@ -204,14 +208,16 @@ def dynamic_proxytype(handler, cls):
204
208
 
205
209
  spec = {}
206
210
 
211
+ def wrap(func): return utils.wrapped_function(handler = handler, target = func)
212
+
207
213
  for name in superdict(cls).keys():
208
214
  if name not in blacklist:
209
215
  value = getattr(cls, name)
210
216
  if is_descriptor(value):
211
217
  if utils.is_method_descriptor(value):
212
- spec[name] = utils.wrapped_function(handler = handler, target = value)
213
- else:
214
- spec[name] = DescriptorProxy(handler = handler, target = value)
218
+ spec[name] = wrap(value)
219
+ # else:
220
+ # spec[name] = DescriptorProxy(handler = handler, target = value)
215
221
 
216
222
  # to_proxy = [m for m in methods(cls) if m not in blacklist]
217
223
 
@@ -219,8 +225,8 @@ def dynamic_proxytype(handler, cls):
219
225
 
220
226
  # spec = { name: wrap(getattr(cls, name)) for name in to_proxy }
221
227
 
222
- # spec['__getattr__'] = wrap(getattr)
223
- # spec['__setattr__'] = wrap(setattr)
228
+ spec['__getattr__'] = wrap(getattr)
229
+ spec['__setattr__'] = wrap(setattr)
224
230
 
225
231
  if utils.yields_callable_instances(cls):
226
232
  spec['__call__'] = handler
@@ -113,121 +113,38 @@ class RecordProxySystem(ProxySystem):
113
113
  def write_error(cls, val, traceback):
114
114
  error(cls, val)
115
115
 
116
- self.set_thread_id = functional.partial(utils.set_thread_id, self.writer)
116
+ # self.set_thread_id = functional.partial(utils.set_thread_id, self.writer)
117
117
 
118
118
  def watch(f): return functional.either(self.thread_switch_monitor, f)
119
119
 
120
+ # w = self.writer.handle('TRACE')
121
+ # def foo(name, *args):
122
+ # print(f'writing: {self.writer.messages_written} {name} {args}')
123
+ # w(self.writer.messages_written, name, *args)
124
+
125
+ # tracer = Tracer(tracing_config, writer = foo)
120
126
  tracer = Tracer(tracing_config, writer = self.writer.handle('TRACE'))
121
127
 
122
128
  self.wrap_int_to_ext = watch
123
129
 
124
130
  self.on_int_call = functional.mapargs(transform = serialize, function = self.writer.handle('CALL'))
125
131
 
126
- # self.on_ext_result = functional.if_then_else(
127
- # functional.isinstanceof(str),
128
- # self.writer.handle('RESULT'),
129
- # functional.sequence(serialize, self.writer))
130
-
131
- self.on_ext_result = functional.sequence(serialize,
132
- self.writer.handle('RESULT'))
132
+ self.on_ext_result = functional.sequence(serialize, self.writer.handle('RESULT'))
133
133
 
134
134
  self.on_ext_error = write_error
135
135
 
136
136
  self.ext_apply = self.int_apply = functional.apply
137
137
 
138
- super().__init__(thread_state = thread_state, tracer = tracer, immutable_types = immutable_types)
138
+ super().__init__(thread_state = thread_state,
139
+ tracer = tracer,
140
+ immutable_types = immutable_types)
139
141
 
140
- def dynamic_ext_proxytype(self, cls):
142
+ def ext_proxytype(self, cls):
141
143
 
142
- proxytype = super().dynamic_ext_proxytype(cls)
144
+ proxytype = super().ext_proxytype(cls)
143
145
 
144
146
  ref = self.writer.handle(StubRef(proxytype))
145
-
146
- # blacklist = ['__class__', '__dict__', '__module__', '__doc__']
147
-
148
- # methods = []
149
- # members = []
150
-
151
- # for key,value in proxytype.__dict__.items():
152
- # if key not in blacklist:
153
- # if utils.is_method_descriptor(value):
154
- # methods.append(key)
155
- # elif not key.startswith("__retrace"):
156
- # members.append(key)
157
-
158
- # ref = self.writer.handle(StubRef(
159
- # name = cls.__name__,
160
- # module = cls.__module__,
161
- # methods = methods,
162
- # members = members))
163
-
164
- # list(proxytype.__dict__.keys())
165
-
166
- # if resolveable_name(cls):
167
- # module, name = resolveable_name(cls)
168
- # ref = self.writer.handle(StubRef(type = 'dynamic', name = name, module = module))
169
- # else:
170
- # blacklist = ['__getattribute__']
171
- # descriptors = {k: v for k,v in superdict(cls).items() if k not in blacklist and is_descriptor(v) }
172
-
173
- # methods = [k for k, v in descriptors.items() if utils.is_method_descriptor(v)]
174
- # members = [k for k, v in descriptors.items() if not utils.is_method_descriptor(v)]
175
-
176
- # ref = self.writer.handle(ProxySpec(name = cls.__name__,
177
- # module = cls.__module__,
178
- # methods = methods,
179
- # members = members))
180
147
 
181
148
  self.writer.type_serializer[proxytype] = functional.constantly(ref)
182
149
 
183
150
  return proxytype
184
-
185
- def ext_proxytype(self, cls):
186
- assert isinstance(cls, type), f"record.proxytype requires a type but was passed: {cls}"
187
-
188
- # resolved = resolve(cls)
189
-
190
- proxytype = super().ext_proxytype(cls)
191
-
192
- assert resolve(cls) is cls
193
-
194
- # ref = self.writer.handle(StubRef(name = cls.__name__,
195
- # module = cls.__module__))
196
-
197
- # if resolveable_name(cls):
198
- # module, name = resolveable_name(cls)
199
- # ref = self.writer.handle(StubRef(name = cls.__name__, module = cls.__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
214
-
215
-
216
- def extend_type(self, cls):
217
-
218
- if cls in self.extended_types:
219
- return self.extended_types[cls]
220
-
221
- extended = super().extend_type(cls)
222
-
223
- self.extended_types[cls] = extended
224
-
225
- ref = self.writer.handle(ExtendedRef(name = cls.__name__,
226
- module = cls.__module__))
227
-
228
- # for binding?
229
- # self.writer(ref)
230
-
231
- self.writer.type_serializer[extended] = functional.constantly(ref)
232
-
233
- return extended
@@ -78,22 +78,6 @@ def on_stack_mismatch(last_matching, record, replay):
78
78
 
79
79
  class ReplayProxySystem(ProxySystem):
80
80
 
81
- # def stubtype(self, cls):
82
- # assert not issubclass(cls, Proxy)
83
-
84
- # return dynamic_proxytype(handler = self.ext_handler, cls = cls)
85
-
86
- def create_stub(self): return True
87
-
88
- # def stubtype_from_spec(self, spec):
89
- # print (f'FOOO!!! {spec}')
90
- # return stubtype_from_spec(
91
- # handler = self.ext_handler,
92
- # module = spec.module,
93
- # name = spec.name,
94
- # methods = spec.methods,
95
- # members = spec.members)
96
-
97
81
  @utils.striptraceback
98
82
  def next_result(self):
99
83
  while True:
@@ -113,6 +97,7 @@ class ReplayProxySystem(ProxySystem):
113
97
  return self.messages()
114
98
 
115
99
  elif next == 'ERROR':
100
+ # breakpoint()
116
101
  err_type = self.messages()
117
102
  err_value = self.messages()
118
103
  utils.raise_exception(err_type, err_value)
@@ -152,6 +137,66 @@ class ReplayProxySystem(ProxySystem):
152
137
  def basetype(self, cls):
153
138
  return self.stub_factory.create_stubtype(StubRef(cls))
154
139
 
140
+
141
+ def readnext(self):
142
+ with self.thread_state.select('disabled'):
143
+ try:
144
+ # obj = self.messages()
145
+ # print(f'read {obj}')
146
+ # return obj
147
+ return self.messages()
148
+ except Exception as error:
149
+ # print(f'Error reading stream: {error}')
150
+ traceback.print_exc()
151
+ os._exit(1)
152
+
153
+ def read_required(self, required):
154
+ obj = self.readnext()
155
+ if obj != required:
156
+ if self.last_matching_stack:
157
+ for line in self.last_matching_stack:
158
+ print(line)
159
+
160
+ print('---------------------------------')
161
+ print(f'Replay: {required}')
162
+ print('---------------------------------')
163
+ print(f'Record: {obj}')
164
+ print('---------------------------------')
165
+ for i in range(15):
166
+ print(self.readnext())
167
+
168
+ breakpoint()
169
+ os._exit(1)
170
+ raise Exception(f'Expected: {required} but got: {obj}')
171
+
172
+ self.last_matching_stack = utils.stacktrace()
173
+
174
+ def trace_writer(self, name, *args):
175
+ with self.thread_state.select('disabled'):
176
+ # read = self.messages_read
177
+
178
+ self.read_required('TRACE')
179
+ # self.read_required(read)
180
+ self.read_required(name)
181
+
182
+ if name == 'stacktrace':
183
+ record = self.readnext()
184
+ if args[0] == record:
185
+ self.last_matching_stack = args[0]
186
+ else:
187
+ on_stack_mismatch(
188
+ last_matching = self.last_matching_stack,
189
+ record = record,
190
+ replay = args[0])
191
+ os._exit(1)
192
+ else:
193
+ # print(f'Trace: {self.reader.messages_read} {name} {args}')
194
+ for arg in args:
195
+ self.read_required(arg)
196
+
197
+ def sync(self, function):
198
+ return utils.observer(on_call = functional.always(self.read_sync), function = function)
199
+
155
200
  def __init__(self,
156
201
  thread_state,
157
202
  immutable_types,
@@ -159,152 +204,29 @@ class ReplayProxySystem(ProxySystem):
159
204
  path,
160
205
  fork_path = []):
161
206
 
162
- # self.writer = writer
163
- # super().__init__(thread_state = thread_state)
164
- reader = stream.reader(path)
207
+ # self.messages_read = 0
208
+ self.reader = stream.reader(path)
165
209
 
166
210
  self.bindings = utils.id_dict()
167
211
  self.set_thread_id = utils.set_thread_id
168
212
  self.fork_path = fork_path
169
213
  deserialize = functional.walker(self.bindings.get_else_key)
170
214
 
171
- self.messages = functional.sequence(per_thread_messages(reader), deserialize)
172
-
173
- self.stub_factory = StubFactory(thread_state = thread_state, next_result = self.next_result)
174
-
175
- # messages = reader
176
-
177
- def readnext():
178
- with thread_state.select('disabled'):
179
- try:
180
- return self.messages()
181
- except Exception as error:
182
- # print(f'Error reading stream: {error}')
183
- traceback.print_exc()
184
-
185
- os._exit(1)
186
-
187
- # print(f'read: {obj}')
188
- # return obj
189
-
190
-
191
- # lookup = weakref.WeakKeyDictionary()
215
+ # def count(res):
216
+ # self.messages_read += 1
217
+ # return res
192
218
 
193
- # debug = debug_level(config)
194
-
195
- # int_refs = {}
196
- last_matching_stack = None
197
-
198
- def read_required(required):
199
- obj = readnext()
200
- if obj != required:
201
- if last_matching_stack:
202
- for line in last_matching_stack:
203
- print(line)
204
-
205
- print('---------------------------------')
206
- print(f'Replay: {required}')
207
- print('---------------------------------')
208
- print(f'Record: {obj}')
209
- print('---------------------------------')
210
- for i in range(5):
211
- print(readnext())
212
-
213
- utils.sigtrap(None)
214
- os._exit(1)
215
- raise Exception(f'Expected: {required} but got: {obj}')
216
-
217
- def trace_writer(name, *args):
218
- with thread_state.select('disabled'):
219
- read_required('TRACE')
220
- read_required(name)
221
-
222
- if name == 'stacktrace':
223
- record = readnext()
224
- if args[0] == record:
225
- nonlocal last_matching_stack
226
- last_matching_stack = args[0]
227
- else:
228
- on_stack_mismatch(
229
- last_matching= last_matching_stack,
230
- record = record,
231
- replay = args[0])
232
- os._exit(1)
233
- else:
234
- print(f'Trace: {name} {args}')
235
- for arg in args:
236
- read_required(arg)
237
-
238
- # self.tracer = Tracer(tracing_config, writer = trace_writer)
239
- # self.immutable_types = immutable_types
240
-
241
- self.reader = reader
242
-
243
- # def foo(cls):
244
- # print(cls)
245
- # assert isinstance(cls, type)
246
- # immutable_types.add(cls)
247
-
248
- # add_stubtype = functional.side_effect(foo)
249
- # add_stubtype = functional.side_effect(immutable_types.add)
250
-
251
- # reader.type_deserializer[ProxyRef] = functional.sequence(lambda ref: ref.resolve(), self.stubtype, add_stubtype)
252
-
253
- reader.type_deserializer[StubRef] = self.stub_factory
254
- # reader.type_deserializer[ProxySpec] = functional.sequence(self.stubtype_from_spec, add_stubtype)
219
+ self.messages = functional.sequence(per_thread_messages(self.reader),
220
+ deserialize)
255
221
 
256
- # on_ext_result = functional.if_then_else(
257
- # functional.is_instanceof(str), writer.handle('RESULT'), writer)
258
-
259
- # def int_proxytype(gateway):
260
- # return lambda cls: dynamic_int_proxytype(handler = gateway, cls = cls, bind = self.bind)
261
-
262
- # create_stubs = functional.walker(functional.when(is_stub_ref, lambda stub: stub.create()))
263
- # create_stubs = functional.walker(functional.when(is_stub_type, lambda cls: cls()))
222
+ self.stub_factory = StubFactory(thread_state = thread_state, next_result = self.next_result)
264
223
 
265
- # self.ext_apply = functional.repeatedly(functional.sequence(self.next_result, create_stubs))
266
- # self.ext_apply = functional.repeatedly(self.next_result)
267
-
268
- def read_sync(): read_required('SYNC')
224
+ self.last_matching_stack = None
269
225
 
270
- self.sync = lambda function: utils.observer(on_call = functional.always(read_sync), function = function)
226
+ self.reader.type_deserializer[StubRef] = self.stub_factory
227
+
228
+ self.read_sync = functional.always(lambda: self.read_required('SYNC'))
271
229
 
272
230
  super().__init__(thread_state = thread_state,
273
- tracer = Tracer(tracing_config, writer = trace_writer),
231
+ tracer = Tracer(tracing_config, writer = self.trace_writer),
274
232
  immutable_types = immutable_types)
275
-
276
- # super().__init__(
277
- # thread_state=thread_state,
278
- # immutable_types= immutable_types,
279
- # tracer=self.tracer,
280
- # ext_apply = ext_apply)
281
-
282
- # self.ext_handler, self.int_handler = gateway_pair(
283
- # thread_state,
284
- # self.tracer,
285
- # immutable_types = immutable_types,
286
- # ext_apply = ext_apply,
287
- # int_proxytype = int_proxytype,
288
- # ext_proxytype = functional.identity)
289
-
290
- # def extend_type(self, base):
291
-
292
- # # ok, how to provide __getattr__ style access,
293
-
294
- # extended = extending_proxytype(
295
- # cls = base,
296
- # thread_state = self.thread_state,
297
- # int_handler = self.int_handler,
298
- # ext_handler = self.ext_handler,
299
- # on_subclass_new = self.bind,
300
- # is_stub = True)
301
-
302
- # self.immutable_types.add(extended)
303
- # # proxytype = extending_proxytype(base)
304
-
305
- # # make_extensible(cls = extended,
306
- # # int_handler = self.int_handler,
307
- # # ext_handler = self.ext_handler,
308
- # # on_new = self.reader.supply)
309
-
310
- # return extended
@@ -17,19 +17,15 @@ class StubRef:
17
17
  blacklist = ['__class__', '__dict__', '__module__', '__doc__', '__new__']
18
18
 
19
19
  methods = []
20
- members = []
21
20
 
22
21
  for key,value in cls.__dict__.items():
23
22
  if key not in blacklist:
24
23
  if utils.is_method_descriptor(value):
25
24
  methods.append(key)
26
- elif not key.startswith("__retrace"):
27
- members.append(key)
28
25
 
29
26
  self.name = cls.__name__
30
27
  self.module = cls.__module__
31
28
  self.methods = methods
32
- self.members = members
33
29
 
34
30
  # def __init__(self, module, name, methods, members):
35
31
  # self.name = name
@@ -38,7 +34,7 @@ class StubRef:
38
34
  # self.members = members
39
35
 
40
36
  def __str__(self):
41
- return f'StubRef(module = {self.module}, name = {self.name}, methods = {self.methods}, members = {self.members})'
37
+ return f'StubRef(module = {self.module}, name = {self.name}, methods = {self.methods})'
42
38
 
43
39
  def resolve(module, name):
44
40
  try:
@@ -103,7 +99,7 @@ class StubFactory:
103
99
  next_result = self.thread_state.dispatch(disabled, external = self.next_result)
104
100
 
105
101
  return StubMemberDescriptor(name = name, next_result = next_result)
106
-
102
+
107
103
  def create_method(self, name):
108
104
 
109
105
  def disabled(*args, **kwargs):
@@ -133,8 +129,24 @@ class StubFactory:
133
129
  slots[method] = self.create_method(method)
134
130
  assert utils.is_method_descriptor(slots[method])
135
131
 
136
- for member in spec.members:
137
- slots[member] = self.create_member(member)
132
+ def getattr(instance, name):
133
+ if self.thread_state.value == 'external':
134
+ return self.next_result()
135
+ else:
136
+ print(f'Error trying to get attribute: {name}, when retrace mode: {self.thread_state.value} was not external')
137
+ utils.sigtrap(None)
138
+ os._exit(1)
139
+
140
+ def setattr(instance, name, value):
141
+ if self.thread_state.value == 'external':
142
+ return self.next_result()
143
+ else:
144
+ print(f'Error trying to set attribute: {name}, to: {value} when retrace mode: {self.thread_state.value} was not external')
145
+ utils.sigtrap(None)
146
+ os._exit(1)
147
+
148
+ slots['__getattr__'] = getattr
149
+ slots['__setattr__'] = setattr
138
150
 
139
151
  resolved = resolve(spec.module, spec.name)
140
152
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: retracesoftware_proxy
3
- Version: 0.1.8
3
+ Version: 0.1.9
4
4
  License: Apache-2.0
5
5
  Requires-Dist: retracesoftware_utils
6
6
  Requires-Dist: retracesoftware_functional
@@ -1,27 +1,27 @@
1
1
  retracesoftware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- retracesoftware/config.json,sha256=_GTEhl9ba5ed9io_sWAR3nO30T-w66qU6Q-fHKguEHg,8638
2
+ retracesoftware/config.json,sha256=c-bqr6SAuIGpnNRqZLPKW-0-VtG8VyGnqpQPhyc5CFY,8666
3
3
  retracesoftware/install/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  retracesoftware/install/config.py,sha256=EzE5ifQF2lo--hu2njI4T0FJ-zlnWDJV6i7x0DMkVTw,1364
5
5
  retracesoftware/install/edgecases.py,sha256=NR3lyvad9sRsyeDv_Ya8V4xMgPsMPOi9rMcnFOJGOEA,6330
6
6
  retracesoftware/install/globals.py,sha256=F8XvIoZQQ10gSRalk30dvdKllxlwxkaggYY6FogLDxY,510
7
7
  retracesoftware/install/install.py,sha256=HCD_ji8XCr96b5fNzNdL_8qcEp0Jf05Em7T6GA6u8HU,4969
8
- retracesoftware/install/patcher.py,sha256=aDFSUfR8ZWAkLKm5xMuilTxtQ9-uUrHeFHZmozMkRSU,18756
8
+ retracesoftware/install/patcher.py,sha256=VXYzE01SyDDw3wQ-spZRb5HEcH3MOlod56039zhpJIE,18888
9
9
  retracesoftware/install/predicate.py,sha256=tX7NQc0rGkyyHYO3mduYHcJHbw1wczT53m_Dpkzo6do,2679
10
10
  retracesoftware/install/record.py,sha256=tseF_jV4k4HLPTgBPJdjcahl4EQqagoiisMAdGNC52Q,3257
11
11
  retracesoftware/install/references.py,sha256=A-G651IDOfuo00MkbAdpbIQh_15ChvJ7uAVTSmE6zd4,1721
12
12
  retracesoftware/install/replay.py,sha256=VUiHvQK3mgAJEGmtE2TFs9kXzxdWtsjibEcGkhZVCVE,1830
13
- retracesoftware/install/tracer.py,sha256=Oqh8BhZVQVo1COfSGkFCipZGPB2Dv1b4DK3xBvloRew,4796
13
+ retracesoftware/install/tracer.py,sha256=cHEjiVxIp2iVTJEWndwSbMuiXVyGJQxJYZSGrfpSbCw,5723
14
14
  retracesoftware/install/typeutils.py,sha256=_a1PuwdCsYjG1Nkd77V-flqYtwbD4RkJVKn6Z-xABL4,1813
15
15
  retracesoftware/proxy/__init__.py,sha256=ZlDZIuUmKFsE9Tvfd2EKGabTepqv8nrbr5pQhCM3IKc,193
16
16
  retracesoftware/proxy/gateway.py,sha256=xESohWXkiNm4ZutU0RgWUwxjxcBWRQ4rQyxIGQXv_F4,1590
17
17
  retracesoftware/proxy/proxyfactory.py,sha256=qhOqDfMJnLDNkQs26JqDB431MwjjRhGQi8xupJ45asg,12272
18
- retracesoftware/proxy/proxysystem.py,sha256=F0YSsF6BlDjWrjiApfy12GBopD647ML-UXP8Ovn_CL8,6953
19
- retracesoftware/proxy/proxytype.py,sha256=nwOhAqcVIG4h9uonXWBvQidKSbF4YSuMzrGJFlonk0s,12595
20
- retracesoftware/proxy/record.py,sha256=Ukjrzsv7WMA-2oC6Ji-JgIr0R8pRLyQGkHc8grzKtpE,8000
21
- retracesoftware/proxy/replay.py,sha256=RVsezEZcy4bFdPQAAztfEHz6adm8t5lBDMhpnNAqeok,10510
22
- retracesoftware/proxy/stubfactory.py,sha256=UnRDQHgWv2xTYaMPZPXvsa7WBh10CyItc_hsQdtOhcM,4607
18
+ retracesoftware/proxy/proxysystem.py,sha256=Nf_yKa4gMvKA2RWEUBmyH9m46lbsAdyPzj5jVDh4cs8,7427
19
+ retracesoftware/proxy/proxytype.py,sha256=crq7idJP77Magtv58l_uJCAlTnD2aDTT-Uz14raTSIo,12767
20
+ retracesoftware/proxy/record.py,sha256=vtNsoTHP5gsBVJ6dTGHR7QXHGbKm0eONfGcXOb9fhFk,4696
21
+ retracesoftware/proxy/replay.py,sha256=m4Buxlix09aUJX9JYWG1z4jW8Yvbo2zBV353hsZE5qY,7670
22
+ retracesoftware/proxy/stubfactory.py,sha256=CnP0Sm0tZNwyFIQIPkk7w_soNBDcflNKwICsAoZxSD0,5128
23
23
  retracesoftware/proxy/thread.py,sha256=-SvnyVbANkmX2lLRpOvFtkpdpAoF6DhnnYdOOs7Q8vo,1379
24
- retracesoftware_proxy-0.1.8.dist-info/METADATA,sha256=MiCu-FDSk5wmZv30Kz-R-A8UKJxP-0sLHent41c__5o,202
25
- retracesoftware_proxy-0.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
- retracesoftware_proxy-0.1.8.dist-info/top_level.txt,sha256=hYHsR6txLidmqvjBMITpIHvmJJbmoCAgr76-IpZPRz8,16
27
- retracesoftware_proxy-0.1.8.dist-info/RECORD,,
24
+ retracesoftware_proxy-0.1.9.dist-info/METADATA,sha256=yiJDDJYQ4XQhjSaQq4PPZaW1dH7SHtn7m-Dfbk_CrUs,202
25
+ retracesoftware_proxy-0.1.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
+ retracesoftware_proxy-0.1.9.dist-info/top_level.txt,sha256=hYHsR6txLidmqvjBMITpIHvmJJbmoCAgr76-IpZPRz8,16
27
+ retracesoftware_proxy-0.1.9.dist-info/RECORD,,