retracesoftware-proxy 0.1.6__py3-none-any.whl → 0.1.8__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.
@@ -160,12 +160,24 @@
160
160
  "_imp": {
161
161
  "patch_extension_exec": ["exec_dynamic", "exec_builtin"]
162
162
  },
163
+ "bdb": {
164
+ "methods_with_state": {
165
+ "disabled": {
166
+ "Bdb": ["trace_dispatch"]
167
+ }
168
+ },
169
+ "with_state": {
170
+ "disabled": ["Bdb.trace_dispatch"]
171
+ }
172
+ },
163
173
  "sys": {
164
174
  "with_state": {
165
175
  "disabled": ["excepthook"]
166
176
  },
167
- "with_state_recursive0": {
168
- "disabled": ["settrace", "setprofile"]
177
+ "comment": {
178
+ "with_state_recursive": {
179
+ "disabled": ["settrace", "setprofile"]
180
+ }
169
181
  }
170
182
  },
171
183
 
@@ -264,10 +276,16 @@
264
276
  "open_code": "path",
265
277
  "open": "file"
266
278
  },
267
- "wrap": {
268
- "FileIO.readinfo": "retracesoftware.install.edgecases.readinto",
269
- "BufferedReader.readinfo": "retracesoftware.install.edgecases.readinto",
270
- "BufferedRandom.readinfo": "retracesoftware.install.edgecases.readinto"
279
+ "patchtype": {
280
+ "FileIO": {
281
+ "readinfo": "retracesoftware.install.edgecases.readinto"
282
+ },
283
+ "BufferedReader": {
284
+ "readinfo": "retracesoftware.install.edgecases.readinto"
285
+ },
286
+ "BufferedRandom": {
287
+ "readinfo": "retracesoftware.install.edgecases.readinto"
288
+ }
271
289
  }
272
290
  },
273
291
  "pathlib": {
@@ -323,10 +341,12 @@
323
341
  "gaierror",
324
342
  "timeout"
325
343
  ],
326
- "wrap": {
327
- "socket.recvfrom_into": "retracesoftware.install.edgecases.recvfrom_into",
328
- "socket.recv_into": "retracesoftware.install.edgecases.recv_into",
329
- "socket.recvmsg_into": "retracesoftware.install.edgecases.recvmsg_into"
344
+ "patchtype": {
345
+ "socket": {
346
+ "recvfrom_into": "retracesoftware.install.edgecases.recvfrom_into",
347
+ "recv_into": "retracesoftware.install.edgecases.recv_into",
348
+ "recvmsg_into": "retracesoftware.install.edgecases.recvmsg_into"
349
+ }
330
350
  }
331
351
  },
332
352
  "select": {
@@ -349,8 +369,10 @@
349
369
  "_SSLSocket.write": "write"
350
370
  }
351
371
  },
352
- "wrap": {
353
- "_SSLSocket.read": "retracesoftware.install.edgecases.read"
372
+ "patchtype": {
373
+ "_SSLSocket": {
374
+ "read": "retracesoftware.install.edgecases.read"
375
+ }
354
376
  }
355
377
  },
356
378
  "_random": {
@@ -25,7 +25,7 @@ from retracesoftware.install.config import load_config
25
25
  from functools import wraps
26
26
 
27
27
  import retracesoftware.functional as functional
28
- import retracesoftware_utils as utils
28
+ import retracesoftware.utils as utils
29
29
 
30
30
  from retracesoftware.install import edgecases
31
31
  from functools import partial
@@ -137,9 +137,9 @@ def superdict(cls):
137
137
 
138
138
  return result
139
139
 
140
- def is_method_descriptor(obj):
141
- return isinstance(obj, types.FunctionType) or \
142
- (isinstance(obj, (types.WrapperDescriptorType, types.MethodDescriptorType)) and obj.__objclass__ != object)
140
+ # def is_method_descriptor(obj):
141
+ # return isinstance(obj, types.FunctionType) or \
142
+ # (isinstance(obj, (types.WrapperDescriptorType, types.MethodDescriptorType)) and obj.__objclass__ != object)
143
143
 
144
144
  def wrap_method_descriptors(wrapper, prefix, base):
145
145
  slots = {"__slots__": () }
@@ -150,7 +150,7 @@ def wrap_method_descriptors(wrapper, prefix, base):
150
150
 
151
151
  for name,value in superdict(base).items():
152
152
  if name not in blacklist:
153
- if is_method_descriptor(value):
153
+ if utils.is_method_descriptor(value):
154
154
  setattr(extended, name, wrapper(value))
155
155
 
156
156
  return extended
@@ -179,6 +179,7 @@ class Patcher:
179
179
  self.type_attribute_filter = self.predicate(config['type_attribute_filter'])
180
180
  self.post_commit = post_commit
181
181
  self.exclude_paths = [re.compile(s) for s in config.get('exclude_paths', [])]
182
+ self.typepatcher = {}
182
183
 
183
184
  def is_phase(name): return getattr(getattr(self, name, None), "is_phase", False)
184
185
 
@@ -193,7 +194,21 @@ class Patcher:
193
194
  # print(f'in path_predicate, excluding {path}')
194
195
  return False
195
196
  return True
196
-
197
+
198
+ def on_proxytype(self, cls):
199
+
200
+ def patch(spec):
201
+ for method, transform in spec.items():
202
+ setattr(cls, method, resolve(transform)(getattr(cls, method)))
203
+
204
+ if cls.__module__ in self.modules:
205
+ spec = self.modules[cls.__module__]
206
+
207
+ if 'patchtype' in spec:
208
+ patchtype = spec['patchtype']
209
+ if cls.__name__ in patchtype:
210
+ patch(patchtype[cls.__name__])
211
+
197
212
  @property
198
213
  def disable(self):
199
214
  return self.thread_state.select('disabled')
@@ -314,15 +329,35 @@ class Patcher:
314
329
  for state,elems in spec.items():
315
330
 
316
331
  def wrap(obj):
317
- return functional.recursive_wrap(
318
- callable,
319
- lambda f: self.thread_state.wrap(state, f),
332
+ return functional.recurive_wrap_function(
333
+ functional.partial(self.thread_state.wrap, state),
320
334
  obj)
321
335
 
322
336
  updates.update(map_values(wrap, select_keys(elems, mod_dict)))
323
337
 
324
338
  return updates
325
339
 
340
+ @phase
341
+ def methods_with_state(self, spec, mod_dict):
342
+
343
+ # updates = {}
344
+
345
+ def update(cls, name, f):
346
+ setattr(cls, name, f(getattr(cls, name)))
347
+
348
+ for state,cls_methods in spec.items():
349
+ def wrap(obj):
350
+ assert callable(obj)
351
+ return self.thread_state.wrap(desired_state = state, function = obj)
352
+
353
+ for typename,methodnames in cls_methods.items():
354
+ cls = mod_dict[typename]
355
+
356
+ for methodname in methodnames:
357
+ update(cls, methodname, wrap)
358
+
359
+ return {}
360
+
326
361
  @phase
327
362
  def with_state(self, spec, mod_dict):
328
363
 
@@ -330,7 +365,8 @@ class Patcher:
330
365
 
331
366
  for state,elems in spec.items():
332
367
 
333
- def wrap(obj): return self.thread_state.wrap(desired_state = state, function = obj)
368
+ def wrap(obj):
369
+ return self.thread_state.wrap(desired_state = state, function = obj)
334
370
 
335
371
  updates.update(map_values(wrap, select_keys(elems, mod_dict)))
336
372
 
@@ -377,7 +413,9 @@ class Patcher:
377
413
  name = parts[0]
378
414
  if name in mod_dict:
379
415
  value = mod_dict[name]
380
- assert not isinstance(value, utils.wrapped_function), f"value for key: {name} is already wrapped"
416
+ assert not isinstance(value, utils.wrapped_function), \
417
+ f"value for key: {name} is already wrapped"
418
+
381
419
  if len(parts) == 1:
382
420
  updates[name] = resolve(wrapper_name)(value)
383
421
  elif len(parts) == 2:
@@ -436,9 +474,6 @@ class Patcher:
436
474
 
437
475
  def __call__(self, module):
438
476
 
439
- # if module.__name__ == 'locale':
440
- # utils.sigtrap(None)
441
-
442
477
  if not hasattr(module, '__retrace__'):
443
478
  configs = list(self.configs(module))
444
479
 
@@ -446,6 +481,7 @@ class Patcher:
446
481
  if len(configs) > 1:
447
482
  raise Exception(f'TODO')
448
483
  else:
484
+ module.__retrace__ = None
449
485
  try:
450
486
  self.patch_module_with_name(configs[0], module)
451
487
  except Exception as error:
@@ -518,6 +554,8 @@ def install(mode):
518
554
  system = system,
519
555
  post_commit = getattr(system, 'on_patched', None),
520
556
  immutable_types = immutable_types)
557
+
558
+ system.on_proxytype = patcher.on_proxytype
521
559
 
522
560
  def at_exit(): thread_state.value = 'disabled'
523
561
 
@@ -54,7 +54,7 @@ class ProxySystem:
54
54
 
55
55
  def on_ext_error(self, err_type, err_value, err_traceback):
56
56
  pass
57
-
57
+
58
58
  # def stacktrace(self):
59
59
  # self.tracer.stacktrace()
60
60
 
@@ -120,18 +120,20 @@ class ProxySystem:
120
120
  def create_stub(self): return False
121
121
 
122
122
  def int_proxytype(self, cls):
123
- return dynamic_int_proxytype(
123
+ proxytype = dynamic_int_proxytype(
124
124
  handler = self.int_dispatch,
125
125
  cls = cls,
126
126
  bind = self.bind)
127
+
128
+ if self.on_proxytype: self.on_proxytype(proxytype)
129
+ return proxytype
130
+
127
131
 
128
132
  def dynamic_ext_proxytype(self, cls):
129
133
 
130
- proxytype = dynamic_proxytype(
131
- handler = self.ext_dispatch,
132
- cls = cls)
133
- if self.on_proxytype:
134
- self.on_proxytype(proxytype)
134
+ proxytype = dynamic_proxytype(handler = self.ext_dispatch, cls = cls)
135
+
136
+ if self.on_proxytype: self.on_proxytype(proxytype)
135
137
 
136
138
  return proxytype
137
139
 
@@ -146,15 +148,12 @@ class ProxySystem:
146
148
  def ext_proxytype(self, cls):
147
149
  assert isinstance(cls, type)
148
150
  if utils.is_extendable(cls):
149
- return self.extend_type(cls)
150
- else:
151
- return self.proxy_function(cls)
152
-
153
- # return instantiable_dynamic_proxytype(
154
- # handler = self.ext_dispatch,
155
- # cls = cls,
156
- # thread_state = self.thread_state,
157
- # create_stub = self.create_stub())
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})
158
157
 
159
158
  def basetype(self, cls):
160
159
  return cls
@@ -199,6 +198,7 @@ class ProxySystem:
199
198
 
200
199
  else:
201
200
  proxytype = dynamic_proxytype(handler = self.ext_dispatch, cls = type(obj))
201
+ if self.on_proxytype: self.on_proxytype(proxytype)
202
202
 
203
203
  return utils.create_wrapped(proxytype, obj)
204
204
  # raise Exception(f'object {obj} was not proxied as its not a extensible type and is not callable')
@@ -186,6 +186,7 @@ class ExtendingDescriptorProxy:
186
186
  return self.handler(getter, self.name)
187
187
 
188
188
  def __set__(self, instance, value):
189
+ breakpoint()
189
190
  setter = functional.partial(setattr, super(self.proxytype, instance))
190
191
  return self.handler(setter, self.name, value)
191
192
 
@@ -314,6 +315,11 @@ def create_unproxied_type(cls):
314
315
 
315
316
  bases = tuple(map(unproxy_type, cls.__bases__))
316
317
  slots = dict(cls.__dict__)
318
+
319
+ if '__slots__' in slots:
320
+ for slot in slots['__slots__']:
321
+ slots.pop(slot)
322
+
317
323
  # del slots['__init_subclass__']
318
324
  return type(cls.__name__, tuple(bases), slots)
319
325
 
@@ -357,7 +363,8 @@ def extending_proxytype(cls, base, thread_state, ext_handler, int_handler, on_su
357
363
  extended = type(cls.__name__, (base, ExtendingProxy), slots)
358
364
 
359
365
  for name in descriptors:
360
- proxy = ExtendingDescriptorProxy(handler = ext_handler, name = name, proxytype = extended)
366
+ # proxy = ExtendingDescriptorProxy(handler = ext_handler, name = name, proxytype = extended)
367
+ proxy = DescriptorProxy(handler = ext_handler, target = getattr(cls, name))
361
368
  setattr(extended, name, proxy)
362
369
 
363
370
  def unproxied__new__(subclass, *args, **kwargs):
@@ -70,6 +70,13 @@ class RecordProxySystem(ProxySystem):
70
70
  self.thread_state.value = self.saved_thread_state
71
71
  self.writer.reopen()
72
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
80
  def __init__(self, thread_state,
74
81
  immutable_types,
75
82
  tracing_config,
@@ -95,11 +102,11 @@ class RecordProxySystem(ProxySystem):
95
102
 
96
103
  serialize = functional.walker(self.bindings.get_else_key)
97
104
 
98
- thread_switch_monitor = \
105
+ self.thread_switch_monitor = \
99
106
  utils.thread_switch_monitor(
100
107
  functional.repeatedly(functional.sequence(utils.thread_id, self.writer)))
101
108
 
102
- self.sync = lambda function: functional.firstof(thread_switch_monitor, functional.always(self.writer.handle('SYNC')), function)
109
+ # self.sync = lambda function: functional.firstof(self.thread_switch_monitor, functional.always(self.writer.handle('SYNC')), function)
103
110
 
104
111
  error = self.writer.handle('ERROR')
105
112
 
@@ -108,7 +115,7 @@ class RecordProxySystem(ProxySystem):
108
115
 
109
116
  self.set_thread_id = functional.partial(utils.set_thread_id, self.writer)
110
117
 
111
- def watch(f): return functional.either(thread_switch_monitor, f)
118
+ def watch(f): return functional.either(self.thread_switch_monitor, f)
112
119
 
113
120
  tracer = Tracer(tracing_config, writer = self.writer.handle('TRACE'))
114
121
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: retracesoftware_proxy
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  License: Apache-2.0
5
5
  Requires-Dist: retracesoftware_utils
6
6
  Requires-Dist: retracesoftware_functional
@@ -1,11 +1,11 @@
1
1
  retracesoftware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- retracesoftware/config.json,sha256=fzfxZF6ES2NuPO9u9fNX8xMZ5rKZStxAHovsVTSJYzs,8276
2
+ retracesoftware/config.json,sha256=_GTEhl9ba5ed9io_sWAR3nO30T-w66qU6Q-fHKguEHg,8638
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=5tRC8XmJW0_loqX1Nqad1rkG--LlX46YwgbbMTbgASc,17598
8
+ retracesoftware/install/patcher.py,sha256=aDFSUfR8ZWAkLKm5xMuilTxtQ9-uUrHeFHZmozMkRSU,18756
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
@@ -15,13 +15,13 @@ retracesoftware/install/typeutils.py,sha256=_a1PuwdCsYjG1Nkd77V-flqYtwbD4RkJVKn6
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=W2v0Tj0tJeAt_bg9LljQm2iwWpjNIbqUTQ92WK22TF8,6861
19
- retracesoftware/proxy/proxytype.py,sha256=0jbiH8DWgyf7GCPpJMxSzWKvE7kyw1l7SSR7fIXkKDc,12389
20
- retracesoftware/proxy/record.py,sha256=ZsJV0o-Qy874VFObtsfkSF8u9gvyUSee0UPpf9Jq6Es,7734
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
21
  retracesoftware/proxy/replay.py,sha256=RVsezEZcy4bFdPQAAztfEHz6adm8t5lBDMhpnNAqeok,10510
22
22
  retracesoftware/proxy/stubfactory.py,sha256=UnRDQHgWv2xTYaMPZPXvsa7WBh10CyItc_hsQdtOhcM,4607
23
23
  retracesoftware/proxy/thread.py,sha256=-SvnyVbANkmX2lLRpOvFtkpdpAoF6DhnnYdOOs7Q8vo,1379
24
- retracesoftware_proxy-0.1.6.dist-info/METADATA,sha256=NrUK4_HsArWTs-zDxMXZ5GRD3bEw8iOsbb_mpvl8Mfg,202
25
- retracesoftware_proxy-0.1.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
- retracesoftware_proxy-0.1.6.dist-info/top_level.txt,sha256=hYHsR6txLidmqvjBMITpIHvmJJbmoCAgr76-IpZPRz8,16
27
- retracesoftware_proxy-0.1.6.dist-info/RECORD,,
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,,