retracesoftware-proxy 0.1.22__py3-none-any.whl → 0.2.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.
@@ -198,12 +198,18 @@ class DescriptorProxy:
198
198
 
199
199
  def dynamic_proxytype(handler, cls):
200
200
 
201
+ if cls.__module__.startswith('retracesoftware'):
202
+ print(cls)
203
+ utils.sigtrap('HERE5')
204
+
205
+ assert not cls.__module__.startswith('retracesoftware')
206
+
201
207
  # print(f'In dynamic_proxytype: {cls}')
202
208
 
203
209
  assert not issubclass(cls, Proxy)
204
210
  assert not issubclass(cls, BaseException)
205
211
 
206
- blacklist = ['__getattribute__', '__hash__', '__del__', '__call__']
212
+ blacklist = ['__getattribute__', '__hash__', '__del__', '__call__', '__new__']
207
213
 
208
214
  spec = {}
209
215
 
@@ -211,15 +217,27 @@ def dynamic_proxytype(handler, cls):
211
217
 
212
218
  for name in superdict(cls).keys():
213
219
  if name not in blacklist:
214
- try:
215
- value = getattr(cls, name)
216
- if is_descriptor(value):
217
- if utils.is_method_descriptor(value):
218
- spec[name] = wrap(value)
219
- except Exception as error:
220
- print(f'FOO! {cls} {name} {error}')
221
- breakpoint()
222
- raise
220
+ value = getattr(cls, name)
221
+
222
+ if issubclass(type(value), utils.dispatch):
223
+ value = utils.dispatch.table(value)['disabled']
224
+
225
+ # if is_descriptor(value):
226
+ if utils.is_method_descriptor(value):
227
+ spec[name] = wrap(value)
228
+
229
+ # try:
230
+ # value = getattr(cls, name)
231
+
232
+ # assert type(value) is not utils.dispatch
233
+
234
+ # if is_descriptor(value):
235
+ # if utils.is_method_descriptor(value):
236
+ # spec[name] = wrap(value)
237
+ # except Exception as error:
238
+ # print(f'FOO! {cls} {name} {error}')
239
+ # breakpoint()
240
+ # raise
223
241
 
224
242
  # else:
225
243
  # spec[name] = DescriptorProxy(handler = handler, target = value)
@@ -230,6 +248,12 @@ def dynamic_proxytype(handler, cls):
230
248
 
231
249
  # spec = { name: wrap(getattr(cls, name)) for name in to_proxy }
232
250
 
251
+ # def foo(obj, name, default = None):
252
+ # print(f'dynamic_proxytype.__getattr__: {type(obj).__mro__} {name}')
253
+ # utils.sigtrap(obj)
254
+ # return getattr(obj, name, default)
255
+
256
+ # spec['__getattr__'] = wrap(foo)
233
257
  spec['__getattr__'] = wrap(getattr)
234
258
  spec['__setattr__'] = wrap(setattr)
235
259
 
@@ -7,6 +7,7 @@ from retracesoftware.proxy.proxytype import *
7
7
  from retracesoftware.proxy.proxysystem import ProxySystem
8
8
  from retracesoftware.proxy.thread import write_thread_switch, ThreadSwitch, thread_id
9
9
  from retracesoftware.install.tracer import Tracer
10
+ from retracesoftware.install.patchfindspec import patch_find_spec
10
11
  from retracesoftware.proxy.stubfactory import StubRef, ExtendedRef
11
12
  from retracesoftware.proxy.globalref import GlobalRef
12
13
 
@@ -15,11 +16,11 @@ import os
15
16
  import types
16
17
  import gc
17
18
 
18
- class Placeholder:
19
- __slots__ = ['id', '__weakref__']
19
+ # class Placeholder:
20
+ # __slots__ = ['id', '__weakref__']
20
21
 
21
- def __init__(self, id):
22
- self.id = id
22
+ # def __init__(self, id):
23
+ # self.id = id
23
24
 
24
25
  def keys_where_value(pred, dict):
25
26
  for key,value in dict.items():
@@ -50,13 +51,14 @@ def resolveable_name(obj):
50
51
  # when
51
52
  class RecordProxySystem(ProxySystem):
52
53
 
53
- def bind(self, obj):
54
- self.bindings[obj] = self.writer.handle(Placeholder(self.next_placeholder_id))
55
- self.writer(self.bindings[obj])
56
- self.next_placeholder_id += 1
54
+ # def bind(self, obj):
55
+ # self.bindings[obj] = self.writer.handle(Placeholder(self.next_placeholder_id))
56
+ # self.writer(self.bindings[obj])
57
+ # self.next_placeholder_id += 1
57
58
 
58
59
  def before_fork(self):
59
- self.writer.close()
60
+ self.writer.keep_open = False
61
+ # self.writer.close()
60
62
  super().before_fork()
61
63
  # self.writer.path = self.dynamic_path
62
64
 
@@ -64,107 +66,136 @@ class RecordProxySystem(ProxySystem):
64
66
  new_path = self.new_child_path(self.writer.path)
65
67
  new_path.parent.mkdir()
66
68
  self.writer.path = new_path
69
+ self.writer.keep_open = True
67
70
  super().after_fork_in_child()
68
71
 
69
72
  def after_fork_in_parent(self):
70
73
  super().after_fork_in_parent()
71
74
  self.thread_state.value = self.saved_thread_state
72
- self.writer.reopen()
75
+ self.writer.keep_open = True
76
+ # self.writer.reopen()
73
77
 
74
78
  def set_thread_id(self, id):
75
79
  utils.set_thread_id(self.writer.handle(ThreadSwitch(id)))
76
80
  # utils.set_thread_id(id)
77
81
 
78
- def is_entry_frame(self, frame):
79
- if super().is_entry_frame(frame):
80
- self.write_main_path(frame.function.__code__.co_filename)
81
- return True
82
- return False
82
+ # def is_entry_frame(self, frame):
83
+ # if super().is_entry_frame(frame):
84
+ # self.write_main_path(frame.function.__code__.co_filename)
85
+ # return True
86
+ # return False
87
+
88
+ def create_from_external(self, obj):
89
+ # class of obj is bound
90
+ # can now write type(obj)
91
+
92
+ self.bind(obj)
93
+
94
+ breakpoint()
95
+
96
+ def patch_type(self, cls):
97
+
98
+ patched = super().patch_type(cls)
99
+
100
+ self.writer.type_serializer[patched] = functional.side_effect(self.writer.ext_bind)
101
+
102
+ return patched
103
+
104
+ def exclude_from_stacktrace(self, func):
105
+ self.writer.exclude_from_stacktrace(func)
83
106
 
84
- def __init__(self, thread_state,
107
+ def on_gc_event(self, phase, info):
108
+ if phase == 'start':
109
+ self.writer.stacktraces = False
110
+ self.on_start_collect(info['generation'])
111
+
112
+ elif phase == 'stop':
113
+ self.on_end_collect()
114
+ self.writer.stacktraces = self.stacktraces
115
+
116
+ def __init__(self, thread_state,
117
+ writer,
85
118
  immutable_types,
86
119
  tracing_config,
87
- write_main_path,
88
- path):
120
+ maybe_collect,
121
+ traceargs):
89
122
 
90
123
  self.fork_counter = 0
91
- self.write_main_path = write_main_path
92
-
124
+ # self.write_main_path = write_main_path
125
+
93
126
  self.getpid = thread_state.wrap(
94
127
  desired_state = 'disabled', function = os.getpid)
95
128
 
96
129
  self.pid = self.getpid()
97
130
 
98
- self.writer = stream.writer(path = path, thread = thread_id)
99
-
100
- # def on_switch():
101
- # print(f"On thread switch!!!")
102
- # # print(f"On thread switch!!!: {utils.thread_id().id}")
103
- # # utils.sigtrap(utils.thread_id())
104
- # self.writer(utils.thread_id())
105
- # # utils.sigtrap(utils.thread_id())
106
-
107
- # write = utils.observer(on_call = utils.thread_switch_monitor(on_switch), function = self.writer)
108
-
109
- # w = self.writer.handle('TRACE')
110
- # def trace_writer(*args):
111
- # print(f'Trace: {args}')
112
- # w(*args)
113
-
114
- self.extended_types = {}
115
- self.bindings = utils.id_dict()
116
- self.next_placeholder_id = 0
131
+ self.writer = writer
117
132
 
118
- serialize = functional.walker(self.bindings.get_else_key)
119
-
120
- # def on_switch():
121
- # print("On thread switch!!!")
122
- # # utils.sigtrap(utils.thread_id())
123
- # utils.thread_id()()
124
- # # utils.sigtrap(utils.thread_id())
133
+ self.stacktraces = self.writer.stacktraces
125
134
 
126
- # self.thread_switch_monitor = utils.thread_switch_monitor(on_switch)
135
+ if self.stacktraces:
136
+ def set(status):
137
+ self.writer.stacktraces = status
127
138
 
128
- # self.thread_switch_monitor = utils.thread_switch_monitor(functional.repeatedly(utils.thread_id))
139
+ self.wrap_weakref_callback = functional.sequence(
140
+ self.wrap_weakref_callback,
141
+ lambda callback:
142
+ utils.observer(
143
+ on_call = functional.lazy(set, False),
144
+ on_result = functional.lazy(set, True),
145
+ on_error = functional.lazy(set, True),
146
+ function = callback))
147
+
148
+ self.exclude_from_stacktrace(RecordProxySystem.patch_type)
149
+ self.exclude_from_stacktrace(patch_find_spec.__call__)
129
150
 
130
- # self.sync = lambda function: functional.firstof(self.thread_switch_monitor, functional.always(self.writer.handle('SYNC')), function)
151
+ self.extended_types = {}
131
152
 
132
153
  sync_handle = self.writer.handle('SYNC')
133
154
 
155
+ self.on_ext_call = functional.lazy(utils.runall(maybe_collect, sync_handle) if maybe_collect else sync_handle)
156
+
134
157
  write_sync = thread_state.dispatch(utils.noop, internal = functional.lazy(sync_handle))
135
158
 
136
159
  self.sync = lambda function: \
137
160
  utils.observer(on_call = write_sync, function = function)
138
-
139
161
  error = self.writer.handle('ERROR')
140
162
 
141
163
  def write_error(cls, val, traceback):
164
+ assert isinstance(val, BaseException)
142
165
  error(cls, val)
143
166
 
144
- # self.set_thread_id = functional.partial(utils.set_thread_id, self.writer)
145
-
146
- # w = self.writer.handle('TRACE')
147
- # def foo(name, *args):
148
- # print(f'writing: {self.writer.messages_written} {name} {args}')
149
- # w(self.writer.messages_written, name, *args)
150
-
151
- # tracer = Tracer(tracing_config, writer = foo)
152
167
  tracer = Tracer(tracing_config, writer = self.writer.handle('TRACE'))
153
168
 
154
- # self.wrap_int_to_ext = self.sync
169
+ self.writer.exclude_from_stacktrace(write_error)
170
+ # self.writer.exclude_from_stacktrace(Tracer.write_call)
155
171
 
156
- self.on_int_call = functional.mapargs(transform = serialize, function = self.writer.handle('CALL'))
172
+ self.on_int_call = self.writer.handle('CALL')
157
173
 
158
- self.on_ext_result = functional.sequence(serialize, self.writer.handle('RESULT'))
174
+ # write_new_ref = self.writer.handle('RESULT')
175
+
176
+ self.on_ext_result = self.writer.handle('RESULT')
159
177
 
160
178
  self.on_ext_error = write_error
161
179
 
162
- self.ext_apply = self.int_apply = functional.apply
163
-
164
180
  self.writer.type_serializer[types.ModuleType] = GlobalRef
165
181
 
182
+ self.bind = self.writer.bind
183
+
184
+ self.create_from_external = self.writer.ext_bind
185
+
186
+ self.write_trace = self.writer.handle('TRACER')
187
+
188
+ self.checkpoint = self.writer.handle('CHECKPOINT')
189
+
190
+ self.on_weakref_callback_start = functional.lazy(self.writer.handle('ON_WEAKREF_CALLBACK_START'))
191
+ self.on_weakref_callback_end = functional.lazy(self.writer.handle('ON_WEAKREF_CALLBACK_END'))
192
+
193
+ self.on_start_collect = self.writer.handle('ON_START_COLLECT')
194
+ self.on_end_collect = self.writer.handle('ON_END_COLLECT')
195
+
166
196
  super().__init__(thread_state = thread_state,
167
197
  tracer = tracer,
198
+ traceargs = traceargs,
168
199
  immutable_types = immutable_types)
169
200
 
170
201
  def ext_proxytype(self, cls):
@@ -172,7 +203,9 @@ class RecordProxySystem(ProxySystem):
172
203
  proxytype = super().ext_proxytype(cls)
173
204
 
174
205
  ref = self.writer.handle(StubRef(proxytype))
175
-
206
+
176
207
  self.writer.type_serializer[proxytype] = functional.constantly(ref)
177
208
 
178
209
  return proxytype
210
+
211
+
@@ -1,146 +1,20 @@
1
1
  import retracesoftware.functional as functional
2
2
  import retracesoftware_utils as utils
3
- import retracesoftware.stream as stream
4
3
 
5
4
  from retracesoftware.install.tracer import Tracer
6
5
  from retracesoftware.proxy.thread import per_thread_messages, thread_id
6
+ from retracesoftware.proxy.messagestream import *
7
7
  from retracesoftware.proxy.proxytype import *
8
8
  # from retracesoftware.proxy.gateway import gateway_pair
9
- from retracesoftware.proxy.record import StubRef, Placeholder
10
- from retracesoftware.proxy.proxysystem import ProxySystem, RetraceError
11
- from retracesoftware.proxy.stubfactory import StubFactory, Stub, StubFunction
9
+ from retracesoftware.proxy.record import StubRef
10
+ from retracesoftware.proxy.proxysystem import ProxySystem
11
+ from retracesoftware.proxy.stubfactory import StubFactory
12
12
  from retracesoftware.proxy.globalref import GlobalRef
13
13
 
14
14
  import os
15
- import weakref
16
- import traceback
17
- import pprint
18
-
19
- from itertools import count, islice
20
-
21
- # we can have a dummy method descriptor, its has a __name__ and when called, returns the next element
22
-
23
- # for types, we can patch the __new__ method
24
- # do it from C and immutable types can be patched too
25
- # patch the tp_new pointer?
26
-
27
- class ReplayError(RetraceError):
28
- pass
29
-
30
- def count_matching(*lists):
31
- count = 0
32
- for slice in zip(*lists):
33
- if len(set(slice)) == 1:
34
- count += 1
35
- else:
36
- break
37
-
38
- return count
39
-
40
- def on_stack_mismatch(last_matching, record, replay):
41
- # print('Common:')
42
- # for index, common, replay, record in zip(count(), last_matching_stack, args[0], record):
43
- # if common == replay == record:
44
- # print(common)
45
- if last_matching:
46
- matching = count_matching(reversed(last_matching),
47
- reversed(record),
48
- reversed(replay))
49
-
50
- print('Common stacktrace:')
51
- for line in reversed(list(islice(reversed(last_matching), matching))):
52
- print(line)
53
-
54
- print('last matching stacktrace:')
55
- for line in islice(last_matching, 0, len(last_matching) - matching):
56
- print(line)
57
-
58
- print('Replay stacktrace:')
59
- for line in islice(replay, 0, len(replay) - matching):
60
- print(line)
61
-
62
- print('Record stacktrace:')
63
- for line in islice(record, 0, len(record) - matching):
64
- print(line)
65
-
66
- print(f'-----------')
67
- else:
68
- matching = count_matching(reversed(record), reversed(replay))
69
-
70
- print('Common stacktrace:')
71
- for line in reversed(list(islice(reversed(record), matching))):
72
- print(line)
73
-
74
- print('Replay stacktrace:')
75
- for line in islice(replay, 0, len(replay) - matching):
76
- print(line)
77
-
78
- print('Record stacktrace:')
79
- for line in islice(record, 0, len(record) - matching):
80
- print(line)
81
-
82
-
83
15
 
84
16
  class ReplayProxySystem(ProxySystem):
85
17
 
86
- @utils.striptraceback
87
- def next_result(self):
88
- try:
89
- while True:
90
- next = self.messages()
91
-
92
- if next == 'CALL':
93
- func = self.messages()
94
- args = self.messages()
95
- kwargs = self.messages()
96
-
97
- try:
98
- func(*args, **kwargs)
99
- except:
100
- pass
101
-
102
- elif next == 'RESULT':
103
- return self.messages()
104
-
105
- elif next == 'ERROR':
106
- # breakpoint()
107
- err_type = self.messages()
108
- err_value = self.messages()
109
- utils.raise_exception(err_type, err_value)
110
- else:
111
- assert type(next) is not str
112
- return next
113
- except TimeoutError:
114
- print(f'timeout for reader, active thread: {self.reader.active_thread}, next_control: {self.reader.next_control}')
115
-
116
- for thread,stack in self.reader.stacktraces.items():
117
- print(f'thread: {thread}')
118
-
119
- formatted_frames = [
120
- (frame.filename, frame.lineno, frame.function, frame.code_context[0].strip() if frame.code_context else None)
121
- for frame in stack
122
- ]
123
- formatted_trace = traceback.format_list(formatted_frames)
124
- print("Traceback (most recent call last):\n" + "".join(formatted_trace))
125
-
126
- utils.sigtrap(None)
127
-
128
- def bind(self, obj):
129
- read = self.messages()
130
-
131
- assert isinstance(read, Placeholder)
132
-
133
- self.bindings[read] = obj
134
-
135
- # def dynamic_path(self):
136
- # if self.getpid() != self.pid:
137
- # self.pid = self.getpid()
138
- # # ok we are in child, calculate new path
139
- # self.path = self.path / f'fork-{self.fork_counter}'
140
- # self.fork_counter = 0
141
-
142
- # return self.path
143
-
144
18
  def after_fork_in_child(self):
145
19
  self.reader.path = self.new_child_path(self.reader.path)
146
20
  super().after_fork_in_child()
@@ -148,11 +22,9 @@ class ReplayProxySystem(ProxySystem):
148
22
  # def dynamic_ext_proxytype(self, cls):
149
23
  # raise Exception('dynamic_ext_proxytype should not be called in replay')
150
24
 
151
- def proxy_function(self, obj):
152
- func = functional.repeatedly(self.next_result)
153
- func.__name__ = obj.__name__
154
-
155
- return super().proxy_function(func)
25
+ @property
26
+ def ext_apply(self):
27
+ return functional.repeatedly(self.next_result)
156
28
 
157
29
  def proxy__new__(self, __new__, *args, **kwargs):
158
30
  func = functional.repeatedly(self.next_result)
@@ -162,45 +34,6 @@ class ReplayProxySystem(ProxySystem):
162
34
  def basetype(self, cls):
163
35
  return self.stub_factory.create_stubtype(StubRef(cls))
164
36
 
165
- def readnext(self):
166
- with self.thread_state.select('disabled'):
167
- try:
168
- # obj = self.messages()
169
- # print(f'read: {obj}')
170
- # return obj
171
- return self.messages()
172
- except Exception as error:
173
- # print(f'Error reading stream: {error}')
174
- traceback.print_exc()
175
- os._exit(1)
176
-
177
- def read_required(self, required):
178
- obj = self.readnext()
179
- if obj != required:
180
- print('---------------------------------')
181
- print('last matching stack')
182
- print('---------------------------------')
183
- if self.last_matching_stack:
184
- for line in self.last_matching_stack:
185
- print(line)
186
-
187
- print('---------------------------------')
188
- print(f'Replay: {required}')
189
- print('---------------------------------')
190
- for line in utils.stacktrace():
191
- print(line)
192
- print('---------------------------------')
193
- print(f'Record: {obj}')
194
- print('---------------------------------')
195
- for i in range(15):
196
- print(self.readnext())
197
-
198
- breakpoint()
199
- os._exit(1)
200
- raise Exception(f'Expected: {required} but got: {obj}')
201
-
202
- # self.last_matching_stack = utils.stacktrace()
203
-
204
37
  def trace_writer(self, name, *args):
205
38
  with self.thread_state.select('disabled'):
206
39
  # read = self.messages_read
@@ -219,7 +52,7 @@ class ReplayProxySystem(ProxySystem):
219
52
  on_stack_mismatch(
220
53
  last_matching = self.last_matching_stack,
221
54
  record = record,
222
- replay = args[0])
55
+ replay = args[0])
223
56
  os._exit(1)
224
57
  else:
225
58
  # print(f'Trace: {self.reader.messages_read} {name} {args}')
@@ -227,69 +60,79 @@ class ReplayProxySystem(ProxySystem):
227
60
  self.read_required(arg)
228
61
 
229
62
  def on_thread_exit(self, thread_id):
230
- print(f'on_thread_exit!!!!')
63
+ # print(f'on_thread_exit!!!!')
231
64
  self.reader.wake_pending()
232
65
 
233
- def is_entry_frame(self, frame):
234
- if super().is_entry_frame(frame) and frame.function.__code__.co_filename == self.mainscript:
235
- return True
236
- return False
237
-
238
66
  def __init__(self,
67
+ reader,
239
68
  thread_state,
240
69
  immutable_types,
241
70
  tracing_config,
242
- mainscript,
243
- path,
244
- fork_path = []):
245
-
246
- # self.messages_read = 0
71
+ traceargs,
72
+ verbose = False,
73
+ fork_path = [],
74
+ skip_weakref_callbacks = False):
247
75
 
248
- self.mainscript = mainscript
76
+ self.reader = reader
77
+ # self.skip_weakref_callbacks = skip_weakref_callbacks
249
78
 
250
- self.reader = stream.reader(path,
251
- thread = thread_id,
252
- timeout_seconds = 60)
253
-
254
- self.bindings = utils.id_dict()
255
- # self.set_thread_id = utils.set_thread_id
256
79
  self.fork_path = fork_path
257
- deserialize = functional.walker(self.bindings.get_else_key)
258
-
259
- # def count(res):
260
- # self.messages_read += 1
261
- # return res
262
80
 
263
- read_res = functional.vector(functional.lazy(getattr, self.reader, 'messages_read'), self.reader)
81
+ self.messages = MessageStream(
82
+ thread_state = thread_state,
83
+ source = reader,
84
+ skip_weakref_callbacks = skip_weakref_callbacks,
85
+ verbose = verbose)
264
86
 
265
- def foo():
266
- try:
267
- messages_read, res = read_res()
268
- if issubclass(type(res), Stub):
269
- print(f'res: {utils.thread_id()} {messages_read} stub: {type(res)}')
270
- else:
271
- print(f'res: {utils.thread_id()} {messages_read} {res}')
272
-
273
- return res
274
- except Exception as error:
275
- print(f'Error reading next result: {error}')
276
- raise(error)
277
-
278
- # self.messages = functional.sequence(per_thread_messages(foo), deserialize)
279
-
280
- self.messages = functional.sequence(self.reader, deserialize)
87
+ self.checkpoint = self.messages.checkpoint
88
+ self.bind = self.messages.bind
89
+ self.next_result = self.messages.result
90
+ self.exclude_from_stacktrace = self.messages.excludes.add
281
91
 
282
92
  self.stub_factory = StubFactory(thread_state = thread_state, next_result = self.next_result)
283
93
 
284
94
  self.last_matching_stack = None
285
95
 
96
+ def run_ref(ref):
97
+ print(f'run_ref!!!! {ref}')
98
+ return ref()
99
+
286
100
  self.reader.type_deserializer[StubRef] = self.stub_factory
287
- self.reader.type_deserializer[GlobalRef] = lambda ref: ref()
288
-
289
- read_sync = thread_state.dispatch(utils.noop, internal = functional.lazy(thread_state.wrap('disabled', self.read_required), 'SYNC'))
101
+ # self.reader.type_deserializer[GlobalRef] = lambda ref: ref()
102
+ self.reader.type_deserializer[GlobalRef] = run_ref
103
+
104
+ excludes = [ReplayProxySystem.trace_writer]
105
+
106
+ for exclude in excludes:
107
+ self.messages.excludes.add(exclude)
108
+
109
+ sync = functional.lazy(self.messages.read_required, 'SYNC')
110
+
111
+ read_sync = thread_state.dispatch(utils.noop, internal = sync)
112
+
113
+ self.on_ext_call = sync
290
114
 
291
115
  self.sync = lambda function: utils.observer(on_call = read_sync, function = function)
116
+
117
+ self.create_from_external = utils.noop
118
+
119
+ if skip_weakref_callbacks:
120
+ self.wrap_weakref_callback = \
121
+ lambda callback: \
122
+ thread_state.dispatch(
123
+ callback, internal = self.disable_for(callback))
124
+ else:
125
+ self.on_weakref_callback_start = functional.lazy(self.messages.read_required, 'ON_WEAKREF_CALLBACK_START')
126
+ self.on_weakref_callback_end = functional.lazy(self.messages.read_required, 'ON_WEAKREF_CALLBACK_END')
292
127
 
293
128
  super().__init__(thread_state = thread_state,
294
129
  tracer = Tracer(tracing_config, writer = self.trace_writer),
295
- immutable_types = immutable_types)
130
+ immutable_types = immutable_types,
131
+ traceargs = traceargs)
132
+
133
+ def write_trace(self, obj):
134
+ if 'TRACER' != self.messages():
135
+ utils.sigtrap(obj)
136
+
137
+ # self.read_required ('TRACER')
138
+ self.read_required(obj)
@@ -0,0 +1,28 @@
1
+ def serializer(obj):
2
+ cls = type(obj)
3
+
4
+ try:
5
+ if issubclass(cls, Enum):
6
+ return str(obj)
7
+
8
+ if issubclass(cls, (tuple, list)):
9
+ return list(map(serializer, obj))
10
+ elif issubclass(cls, dict):
11
+ return {str(serializer(k)):serializer(v) for k,v in obj.items()}
12
+ elif issubclass(cls, int):
13
+ if obj > 1000000 or obj < -1000000:
14
+ return "XXXX"
15
+ else:
16
+ return int(obj)
17
+ elif issubclass(cls, (bool, str, types.NoneType)):
18
+ return obj
19
+ elif issubclass(cls, types.FunctionType):
20
+ return obj.__qualname__
21
+ elif issubclass(cls, types.CellType):
22
+ return getattr(obj, '__qualname__', 'CellType')
23
+ elif issubclass(cls, types.GeneratorType):
24
+ return obj.__qualname__
25
+ else:
26
+ return cleanse(str(obj))
27
+ except:
28
+ return f'Unserializable object of type: {cls}'