retracesoftware-proxy 0.1.12__py3-none-any.whl → 0.1.14__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.
@@ -158,7 +158,12 @@
158
158
 
159
159
  "modules": {
160
160
  "_imp": {
161
- "patch_extension_exec": ["exec_dynamic", "exec_builtin"]
161
+ "patch_extension_exec": ["exec_dynamic", "exec_builtin"],
162
+ "comment": {
163
+ "with_state": {
164
+ "internal": ["create_dynamic"]
165
+ }
166
+ }
162
167
  },
163
168
  "bdb": {
164
169
  "methods_with_state": {
@@ -183,7 +188,11 @@
183
188
 
184
189
  "importlib._bootstrap": {
185
190
  "with_state": {
186
- "bootstrap": ["_load_unlocked", "_find_spec"]
191
+ "bootstrap": [
192
+ "_load_unlocked",
193
+ "_find_spec",
194
+ "_lock_unlock_module",
195
+ "_get_module_lock"]
187
196
  }
188
197
  },
189
198
 
@@ -215,14 +224,20 @@
215
224
  ]
216
225
  },
217
226
  "types": {
227
+ "patch_hash": ["FunctionType"],
218
228
  "immutable_types": [
219
- "TracebackType"
229
+ "TracebackType",
230
+ "ModuleType"
220
231
  ]
221
232
  },
222
233
  "builtins": {
223
- "replace": {
224
- "set": "retracesoftware_utils.set",
225
- "frozenset": "retracesoftware_utils.frozenset"
234
+ "patch_hash": ["object"],
235
+
236
+ "comment": {
237
+ "replace": {
238
+ "set": "retracesoftware_utils.set",
239
+ "frozenset": "retracesoftware_utils.frozenset"
240
+ }
226
241
  },
227
242
  "immutable_types": [
228
243
  "BaseException",
File without changes
@@ -121,9 +121,22 @@ def patch(func):
121
121
  if isinstance(spec, str):
122
122
  return wrapper(self, [spec], mod_dict)
123
123
  elif isinstance(spec, list):
124
- return {name: func(self, mod_dict[name]) for name in spec if name in mod_dict}
124
+ res = {}
125
+ for name in spec:
126
+ if name in mod_dict:
127
+ value = func(self, mod_dict[name])
128
+ if value is not None:
129
+ res[name] = value
130
+ return res
125
131
  elif isinstance(spec, dict):
126
- return {name: func(self, mod_dict[name], value) for name, value in spec.items() if name in mod_dict}
132
+ # return {name: func(self, mod_dict[name], value) for name, value in spec.items() if name in mod_dict}
133
+ res = {}
134
+ for name,value in spec.items():
135
+ if name in mod_dict:
136
+ value = func(self, mod_dict[name], value)
137
+ if value is not None:
138
+ res[name] = value
139
+ return res
127
140
  else:
128
141
  raise Exception('TODO')
129
142
 
@@ -155,6 +168,11 @@ def wrap_method_descriptors(wrapper, prefix, base):
155
168
 
156
169
  return extended
157
170
 
171
+ class PerThread(threading.local):
172
+ def __init__(self):
173
+ self.internal = utils.counter()
174
+ self.externak = utils.counter()
175
+
158
176
  class Patcher:
159
177
 
160
178
  def __init__(self, thread_state, config, system,
@@ -164,7 +182,7 @@ class Patcher:
164
182
  post_commit = None):
165
183
 
166
184
  # validate(config)
167
- # system.set_thread_id(0)
185
+ system.set_thread_id(0)
168
186
  # utils.set_thread_id(0)
169
187
  self.thread_counter = system.sync(utils.counter(1))
170
188
  # self.set_thread_number = set_thread_number
@@ -181,6 +199,13 @@ class Patcher:
181
199
  self.exclude_paths = [re.compile(s) for s in config.get('exclude_paths', [])]
182
200
  self.typepatcher = {}
183
201
 
202
+ per_thread = PerThread()
203
+
204
+ self.hashfunc = self.thread_state.dispatch(
205
+ functional.constantly(None),
206
+ internal = functional.repeatedly(functional.partial(getattr, per_thread, 'internal')),
207
+ external = functional.repeatedly(functional.partial(getattr, per_thread, 'external')))
208
+
184
209
  def is_phase(name): return getattr(getattr(self, name, None), "is_phase", False)
185
210
 
186
211
  self.phases = [(name, getattr(self, name)) for name in Patcher.__dict__.keys() if is_phase(name)]
@@ -303,19 +328,35 @@ class Patcher:
303
328
  source.co_name == '<module>' and inspect.getmodule(source)
304
329
 
305
330
  def exec_wrapper(source, *args,**kwargs):
306
- if self.thread_state.value != 'boostrap' and is_module_exec(source):
307
- with self.thread_state.select('disabled'):
331
+ module = None
332
+
333
+ with self.thread_state.select('disabled'):
334
+ if is_module_exec(source):
308
335
  module = inspect.getmodule(source)
309
- with self.thread_state.select('internal'):
310
- result = exec(source, *args, **kwargs)
311
-
336
+
337
+ if module:
338
+ result = exec(source, *args, **kwargs)
312
339
  self(module)
313
-
314
340
  return result
315
341
  else:
316
342
  return exec(source, *args,**kwargs)
317
343
 
318
- return exec_wrapper
344
+ # if self.thread_state.value != 'bootstrap':
345
+
346
+ # and is_module_exec(source):
347
+ # with self.thread_state.select('disabled'):
348
+ # module = inspect.getmodule(source)
349
+ # with self.thread_state.select('internal'):
350
+ # result = exec(source, *args, **kwargs)
351
+
352
+ # self(module)
353
+
354
+ # return result
355
+ # else:
356
+ # return exec(source, *args,**kwargs)
357
+
358
+ return self.thread_state.dispatch(exec, internal = exec_wrapper)
359
+ # self.thread_state.wrap(desired_state = 'disabled', function = exec_wrapper)
319
360
 
320
361
  @patch
321
362
  def sync_types(self, value):
@@ -372,6 +413,11 @@ class Patcher:
372
413
 
373
414
  return updates
374
415
 
416
+ @patch
417
+ def patch_hash(self, cls):
418
+ print(f'patching hash for: {cls}')
419
+ utils.patch_hash(cls = cls, hashfunc = self.hashfunc)
420
+
375
421
  @patch
376
422
  def patch_extension_exec(self, exec):
377
423
 
@@ -13,9 +13,15 @@ from datetime import datetime
13
13
  import json
14
14
  from pathlib import Path
15
15
 
16
- class ThreadSwitch:
17
- def __init__(self, id):
18
- self.id = id
16
+ # class ThreadSwitch:
17
+ # def __init__(self, id):
18
+ # self.id = id
19
+
20
+ # def __repr__(self):
21
+ # return f'ThreadSwitch<{self.id}>'
22
+
23
+ # def __str__(self):
24
+ # return f'ThreadSwitch<{self.id}>'
19
25
 
20
26
  def write_files(recording_path):
21
27
  with open(recording_path / 'env', 'w') as f:
@@ -1,3 +1,3 @@
1
1
  from retracesoftware.proxy.record import RecordProxySystem
2
2
  from retracesoftware.proxy.replay import ReplayProxySystem
3
- from retracesoftware.proxy.thread import set_thread_id, per_thread_messages
3
+ from retracesoftware.proxy.thread import per_thread_messages
@@ -0,0 +1,31 @@
1
+ import types
2
+ import sys
3
+
4
+ def find_module_name(mod):
5
+ for name,value in sys.modules.items():
6
+ if value is mod:
7
+ return name
8
+
9
+ raise Exception(f"Cannot create GlobalRef as module {mod} not found in sys.modules")
10
+
11
+ class GlobalRef:
12
+ __slots__ = ['parts']
13
+
14
+ def __init__(self, obj):
15
+ if isinstance(obj, types.ModuleType):
16
+ self.parts = (find_module_name(obj),)
17
+ else:
18
+ raise Exception(f"Cannot create GlobalRef from {obj}")
19
+
20
+ def __call__(self):
21
+ module = self.parts[0]
22
+
23
+ if len(self.parts) == 0:
24
+ return module
25
+ else:
26
+ obj = getattr(module, self.parts[1])
27
+
28
+ if len(self.parts) == 1:
29
+ return obj
30
+ else:
31
+ raise Exception(f"TODO")
@@ -214,10 +214,16 @@ def dynamic_proxytype(handler, cls):
214
214
 
215
215
  for name in superdict(cls).keys():
216
216
  if name not in blacklist:
217
- value = getattr(cls, name)
218
- if is_descriptor(value):
219
- if utils.is_method_descriptor(value):
220
- spec[name] = wrap(value)
217
+ try:
218
+ value = getattr(cls, name)
219
+ if is_descriptor(value):
220
+ if utils.is_method_descriptor(value):
221
+ spec[name] = wrap(value)
222
+ except Exception as error:
223
+ print(f'FOO! {cls} {name} {error}')
224
+ breakpoint()
225
+ raise
226
+
221
227
  # else:
222
228
  # spec[name] = DescriptorProxy(handler = handler, target = value)
223
229
 
@@ -5,9 +5,10 @@ import retracesoftware.stream as stream
5
5
  from retracesoftware.proxy.proxytype import *
6
6
  # from retracesoftware.proxy.gateway import gateway_pair
7
7
  from retracesoftware.proxy.proxysystem import ProxySystem
8
- from retracesoftware.proxy.thread import write_thread_switch
8
+ from retracesoftware.proxy.thread import write_thread_switch, ThreadSwitch
9
9
  from retracesoftware.install.tracer import Tracer
10
10
  from retracesoftware.proxy.stubfactory import StubRef, ExtendedRef
11
+ from retracesoftware.proxy.globalref import GlobalRef
11
12
 
12
13
  import sys
13
14
  import os
@@ -69,14 +70,11 @@ class RecordProxySystem(ProxySystem):
69
70
  super().after_fork_in_parent()
70
71
  self.thread_state.value = self.saved_thread_state
71
72
  self.writer.reopen()
72
-
73
- def sync(self, function):
74
- write_sync = functional.always(self.writer.handle('SYNC'))
75
-
76
- return utils.observer(
77
- on_call = functional.firstof(self.thread_switch_monitor, write_sync),
78
- function = function)
79
73
 
74
+ def set_thread_id(self, id):
75
+ utils.set_thread_id(self.writer.handle(ThreadSwitch(id)))
76
+ # utils.set_thread_id(id)
77
+
80
78
  def __init__(self, thread_state,
81
79
  immutable_types,
82
80
  tracing_config,
@@ -91,6 +89,15 @@ class RecordProxySystem(ProxySystem):
91
89
 
92
90
  self.writer = stream.writer(path)
93
91
 
92
+ def on_switch():
93
+ print(f"On thread switch!!!")
94
+ # print(f"On thread switch!!!: {utils.thread_id().id}")
95
+ # utils.sigtrap(utils.thread_id())
96
+ self.writer(utils.thread_id())
97
+ # utils.sigtrap(utils.thread_id())
98
+
99
+ write = utils.observer(on_call = utils.thread_switch_monitor(on_switch), function = self.writer)
100
+
94
101
  # w = self.writer.handle('TRACE')
95
102
  # def trace_writer(*args):
96
103
  # print(f'Trace: {args}')
@@ -102,39 +109,50 @@ class RecordProxySystem(ProxySystem):
102
109
 
103
110
  serialize = functional.walker(self.bindings.get_else_key)
104
111
 
105
- self.thread_switch_monitor = \
106
- utils.thread_switch_monitor(
107
- functional.repeatedly(functional.sequence(utils.thread_id, self.writer)))
112
+ # def on_switch():
113
+ # print("On thread switch!!!")
114
+ # # utils.sigtrap(utils.thread_id())
115
+ # utils.thread_id()()
116
+ # # utils.sigtrap(utils.thread_id())
117
+
118
+ # self.thread_switch_monitor = utils.thread_switch_monitor(on_switch)
119
+
120
+ # self.thread_switch_monitor = utils.thread_switch_monitor(functional.repeatedly(utils.thread_id))
108
121
 
109
122
  # self.sync = lambda function: functional.firstof(self.thread_switch_monitor, functional.always(self.writer.handle('SYNC')), function)
110
-
123
+
124
+ self.sync = lambda function: \
125
+ utils.observer(
126
+ on_call = functional.lazy(write, self.writer.handle('SYNC')),
127
+ function = function)
128
+
111
129
  error = self.writer.handle('ERROR')
112
130
 
113
131
  def write_error(cls, val, traceback):
114
- error(cls, val)
132
+ write(error, cls, val)
115
133
 
116
134
  # self.set_thread_id = functional.partial(utils.set_thread_id, self.writer)
117
135
 
118
- def watch(f): return functional.either(self.thread_switch_monitor, f)
119
-
120
136
  # w = self.writer.handle('TRACE')
121
137
  # def foo(name, *args):
122
138
  # print(f'writing: {self.writer.messages_written} {name} {args}')
123
139
  # w(self.writer.messages_written, name, *args)
124
140
 
125
141
  # tracer = Tracer(tracing_config, writer = foo)
126
- tracer = Tracer(tracing_config, writer = self.writer.handle('TRACE'))
142
+ tracer = Tracer(tracing_config, writer = functional.partial(write, self.writer.handle('TRACE')))
127
143
 
128
- self.wrap_int_to_ext = watch
144
+ # self.wrap_int_to_ext = self.sync
129
145
 
130
- self.on_int_call = functional.mapargs(transform = serialize, function = self.writer.handle('CALL'))
146
+ self.on_int_call = functional.mapargs(transform = serialize, function = functional.partial(write, self.writer.handle('CALL')))
131
147
 
132
- self.on_ext_result = functional.sequence(serialize, self.writer.handle('RESULT'))
148
+ self.on_ext_result = functional.sequence(serialize, functional.partial(write, self.writer.handle('RESULT')))
133
149
 
134
150
  self.on_ext_error = write_error
135
151
 
136
152
  self.ext_apply = self.int_apply = functional.apply
137
153
 
154
+ self.writer.type_serializer[types.ModuleType] = GlobalRef
155
+
138
156
  super().__init__(thread_state = thread_state,
139
157
  tracer = tracer,
140
158
  immutable_types = immutable_types)
@@ -8,7 +8,8 @@ from retracesoftware.proxy.proxytype import *
8
8
  # from retracesoftware.proxy.gateway import gateway_pair
9
9
  from retracesoftware.proxy.record import StubRef, Placeholder
10
10
  from retracesoftware.proxy.proxysystem import ProxySystem, RetraceError
11
- from retracesoftware.proxy.stubfactory import StubFactory, StubFunction
11
+ from retracesoftware.proxy.stubfactory import StubFactory, Stub, StubFunction
12
+ from retracesoftware.proxy.globalref import GlobalRef
12
13
 
13
14
  import os
14
15
  import weakref
@@ -153,6 +154,9 @@ class ReplayProxySystem(ProxySystem):
153
154
  def read_required(self, required):
154
155
  obj = self.readnext()
155
156
  if obj != required:
157
+ print('---------------------------------')
158
+ print('last matching stack')
159
+ print('---------------------------------')
156
160
  if self.last_matching_stack:
157
161
  for line in self.last_matching_stack:
158
162
  print(line)
@@ -160,6 +164,9 @@ class ReplayProxySystem(ProxySystem):
160
164
  print('---------------------------------')
161
165
  print(f'Replay: {required}')
162
166
  print('---------------------------------')
167
+ for line in utils.stacktrace():
168
+ print(line)
169
+ print('---------------------------------')
163
170
  print(f'Record: {obj}')
164
171
  print('---------------------------------')
165
172
  for i in range(15):
@@ -194,9 +201,6 @@ class ReplayProxySystem(ProxySystem):
194
201
  for arg in args:
195
202
  self.read_required(arg)
196
203
 
197
- def sync(self, function):
198
- return utils.observer(on_call = functional.always(self.read_sync), function = function)
199
-
200
204
  def __init__(self,
201
205
  thread_state,
202
206
  immutable_types,
@@ -208,25 +212,44 @@ class ReplayProxySystem(ProxySystem):
208
212
  self.reader = stream.reader(path)
209
213
 
210
214
  self.bindings = utils.id_dict()
211
- self.set_thread_id = utils.set_thread_id
215
+ # self.set_thread_id = utils.set_thread_id
212
216
  self.fork_path = fork_path
213
217
  deserialize = functional.walker(self.bindings.get_else_key)
214
218
 
215
219
  # def count(res):
216
220
  # self.messages_read += 1
217
221
  # return res
222
+
223
+ read_res = functional.vector(functional.lazy(getattr, self.reader, 'messages_read'), self.reader)
224
+
225
+ def foo():
226
+ try:
227
+ messages_read, res = read_res()
228
+ if issubclass(type(res), Stub):
229
+ print(f'res: {utils.thread_id()} {messages_read} stub: {type(res)}')
230
+ else:
231
+ print(f'res: {utils.thread_id()} {messages_read} {res}')
232
+
233
+ return res
234
+ except Exception as error:
235
+ print(f'Error reading next result: {error}')
236
+ raise(error)
218
237
 
219
- self.messages = functional.sequence(per_thread_messages(self.reader),
220
- deserialize)
238
+ self.messages = functional.sequence(per_thread_messages(foo), deserialize)
239
+
240
+ # self.messages = functional.sequence(per_thread_messages(self.reader), deserialize)
221
241
 
222
242
  self.stub_factory = StubFactory(thread_state = thread_state, next_result = self.next_result)
223
243
 
224
244
  self.last_matching_stack = None
225
245
 
226
246
  self.reader.type_deserializer[StubRef] = self.stub_factory
247
+ self.reader.type_deserializer[GlobalRef] = lambda ref: ref()
227
248
 
228
- self.read_sync = functional.always(lambda: self.read_required('SYNC'))
229
-
249
+ read_sync = functional.lazy(self.read_required, 'SYNC')
250
+
251
+ self.sync = lambda function: utils.observer(on_call = read_sync, function = function)
252
+
230
253
  super().__init__(thread_state = thread_state,
231
254
  tracer = Tracer(tracing_config, writer = self.trace_writer),
232
255
  immutable_types = immutable_types)
@@ -11,17 +11,28 @@ class ThreadSwitch:
11
11
  def __init__(self, id):
12
12
  self.id = id
13
13
 
14
- def set_thread_id(writer, id):
15
- utils.set_thread_id(writer.handle(ThreadSwitch(id)))
14
+ def __repr__(self):
15
+ return f'ThreadSwitch<{self.id}>'
16
+
17
+ def __str__(self):
18
+ return f'ThreadSwitch<{self.id}>'
19
+
20
+ # def set_thread_id(writer, id):
21
+ # utils.sigtrap(id)
22
+ # utils.set_thread_id(writer.handle(ThreadSwitch(id)))
16
23
 
17
24
  def write_thread_switch(writer):
18
25
  on_thread_switch = functional.repeatedly(functional.sequence(utils.thread_id, writer))
19
26
 
20
27
  return lambda f: utils.thread_aware_proxy(target = f, on_thread_switch = on_thread_switch, sticky = False)
21
28
 
22
- def prefix_with_thread_id(f, current):
29
+ def prefix_with_thread_id(f, thread_id):
30
+ current = None
31
+
23
32
  def next():
24
33
  nonlocal current, f
34
+ if current is None: current = thread_id()
35
+
25
36
  obj = f()
26
37
 
27
38
  while issubclass(type(obj), ThreadSwitch):
@@ -36,7 +47,8 @@ def per_thread_messages(messages):
36
47
  thread_id = utils.thread_id
37
48
  # thread_id = lambda: 'FOOOOO!!!'
38
49
 
39
- demux = utils.demux(source = prefix_with_thread_id(messages, thread_id()), key_function = lambda obj: obj[0])
50
+ demux = utils.demux(source = prefix_with_thread_id(messages, thread_id),
51
+ key_function = lambda obj: obj[0])
40
52
 
41
53
  # def next():
42
54
  # thread,message = demux(thread_id())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: retracesoftware_proxy
3
- Version: 0.1.12
3
+ Version: 0.1.14
4
4
  License: Apache-2.0
5
5
  Requires-Dist: retracesoftware_utils
6
6
  Requires-Dist: retracesoftware_functional
@@ -1,27 +1,29 @@
1
1
  retracesoftware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- retracesoftware/config.json,sha256=UugFK-HB2zW0Lud8RZ8w0EiP0LSJgB4ob_T7JaU1slI,8709
2
+ retracesoftware/config.json,sha256=JU3LYWZbqBLqiHXDc9fBYVh0owMUcKGw3W-vaVm-roo,9024
3
+ retracesoftware/config.yaml,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
4
  retracesoftware/install/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
5
  retracesoftware/install/config.py,sha256=EzE5ifQF2lo--hu2njI4T0FJ-zlnWDJV6i7x0DMkVTw,1364
5
6
  retracesoftware/install/edgecases.py,sha256=NR3lyvad9sRsyeDv_Ya8V4xMgPsMPOi9rMcnFOJGOEA,6330
6
7
  retracesoftware/install/globals.py,sha256=F8XvIoZQQ10gSRalk30dvdKllxlwxkaggYY6FogLDxY,510
7
8
  retracesoftware/install/install.py,sha256=HCD_ji8XCr96b5fNzNdL_8qcEp0Jf05Em7T6GA6u8HU,4969
8
- retracesoftware/install/patcher.py,sha256=IUkQx5kr4AnniKZ2gWnnx2is1j_y_eb7nz2UKyHyqSA,18894
9
+ retracesoftware/install/patcher.py,sha256=ryX73_KjdcUCC0oy0Uqel_L3bwfZZldS3CIYQ-XAl_k,20520
9
10
  retracesoftware/install/predicate.py,sha256=tX7NQc0rGkyyHYO3mduYHcJHbw1wczT53m_Dpkzo6do,2679
10
- retracesoftware/install/record.py,sha256=tseF_jV4k4HLPTgBPJdjcahl4EQqagoiisMAdGNC52Q,3257
11
+ retracesoftware/install/record.py,sha256=R2GOIA_WAggrNmVwZJh9r1xp-GVu43iKq-ykQ1VKEHE,3408
11
12
  retracesoftware/install/references.py,sha256=A-G651IDOfuo00MkbAdpbIQh_15ChvJ7uAVTSmE6zd4,1721
12
13
  retracesoftware/install/replay.py,sha256=VUiHvQK3mgAJEGmtE2TFs9kXzxdWtsjibEcGkhZVCVE,1830
13
14
  retracesoftware/install/tracer.py,sha256=cHEjiVxIp2iVTJEWndwSbMuiXVyGJQxJYZSGrfpSbCw,5723
14
15
  retracesoftware/install/typeutils.py,sha256=_a1PuwdCsYjG1Nkd77V-flqYtwbD4RkJVKn6Z-xABL4,1813
15
- retracesoftware/proxy/__init__.py,sha256=ZlDZIuUmKFsE9Tvfd2EKGabTepqv8nrbr5pQhCM3IKc,193
16
+ retracesoftware/proxy/__init__.py,sha256=ntIyqKhBRkKEkcW_oOPodikh-mxYl8OXRnSaj-9-Xwc,178
16
17
  retracesoftware/proxy/gateway.py,sha256=xESohWXkiNm4ZutU0RgWUwxjxcBWRQ4rQyxIGQXv_F4,1590
18
+ retracesoftware/proxy/globalref.py,sha256=yXtJsOeBHN9xoEgJWA3MJco-jD2SQUef_fDatA4A6rg,803
17
19
  retracesoftware/proxy/proxyfactory.py,sha256=qhOqDfMJnLDNkQs26JqDB431MwjjRhGQi8xupJ45asg,12272
18
20
  retracesoftware/proxy/proxysystem.py,sha256=ZX6eNT8go-YDbLWD2pq5j_V8DZAHteu-iNfkMO8jLWg,7567
19
- retracesoftware/proxy/proxytype.py,sha256=H6SJKX0izor1yLOK_QxRlfKLcJC08eMuIYJ1amnoZvQ,12812
20
- retracesoftware/proxy/record.py,sha256=vtNsoTHP5gsBVJ6dTGHR7QXHGbKm0eONfGcXOb9fhFk,4696
21
- retracesoftware/proxy/replay.py,sha256=m4Buxlix09aUJX9JYWG1z4jW8Yvbo2zBV353hsZE5qY,7670
21
+ retracesoftware/proxy/proxytype.py,sha256=hP-1vJmWBa9KgZFB3CnZy0UbC4u8Wr2e76lGI0JM2SA,12992
22
+ retracesoftware/proxy/record.py,sha256=QBx3G8mXjUiB9vCXJZ0tZdt3Mi1WEtRhuZ7HOUroNNQ,5505
23
+ retracesoftware/proxy/replay.py,sha256=vVFkhYOOZSprLD_mjx-p6SpDB8fy81SK3x2A5H0odUs,8614
22
24
  retracesoftware/proxy/stubfactory.py,sha256=37UX1r8HCAbASTwPdz8QKCrg72NQmM5PsiCho7N2nzg,5129
23
- retracesoftware/proxy/thread.py,sha256=-SvnyVbANkmX2lLRpOvFtkpdpAoF6DhnnYdOOs7Q8vo,1379
24
- retracesoftware_proxy-0.1.12.dist-info/METADATA,sha256=HH7c48R8UNiCuIlDo-aS85vN6bbdMVl2WqGIjGmU08o,203
25
- retracesoftware_proxy-0.1.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
- retracesoftware_proxy-0.1.12.dist-info/top_level.txt,sha256=hYHsR6txLidmqvjBMITpIHvmJJbmoCAgr76-IpZPRz8,16
27
- retracesoftware_proxy-0.1.12.dist-info/RECORD,,
25
+ retracesoftware/proxy/thread.py,sha256=idkJwJ8rR1kpRHfo81uCi6Y0LEIChAdfc0GqK_bFqTA,1635
26
+ retracesoftware_proxy-0.1.14.dist-info/METADATA,sha256=Y6QfA5aDmUke1rEvUWSOgRIwbEAk7YbbcpW-7m00kQM,203
27
+ retracesoftware_proxy-0.1.14.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
+ retracesoftware_proxy-0.1.14.dist-info/top_level.txt,sha256=hYHsR6txLidmqvjBMITpIHvmJJbmoCAgr76-IpZPRz8,16
29
+ retracesoftware_proxy-0.1.14.dist-info/RECORD,,