ballpython 2.0.0__py3-none-any.whl → 2.0.2__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.
- ballpython/py.typed +0 -0
- {ballpython-2.0.0.dist-info → ballpython-2.0.2.dist-info}/METADATA +13 -7
- ballpython-2.0.2.dist-info/RECORD +34 -0
- pycleaner/__init__.py +39 -2
- pycleaner/baseline.py +127 -0
- pycleaner/cache.py +282 -0
- pycleaner/cli.py +644 -43
- pycleaner/complexity_analyzer.py +16 -28
- pycleaner/config.py +8 -1
- pycleaner/dead_code_detector.py +275 -38
- pycleaner/dependency_auditor.py +175 -75
- pycleaner/discovery.py +206 -0
- pycleaner/explanations.py +323 -0
- pycleaner/frameworks/__init__.py +115 -0
- pycleaner/frameworks/plugins.py +290 -0
- pycleaner/modernizer.py +349 -0
- pycleaner/pipeline.py +208 -20
- pycleaner/py.typed +0 -0
- pycleaner/security_scanner.py +59 -38
- pycleaner/syntax_healer.py +188 -10
- pycleaner/taint_engine.py +8 -8
- pycleaner/test_generator.py +124 -35
- pycleaner/type_checker.py +29 -33
- pycleaner/verifier.py +495 -0
- ballpython-2.0.0.dist-info/RECORD +0 -24
- {ballpython-2.0.0.dist-info → ballpython-2.0.2.dist-info}/WHEEL +0 -0
- {ballpython-2.0.0.dist-info → ballpython-2.0.2.dist-info}/entry_points.txt +0 -0
- {ballpython-2.0.0.dist-info → ballpython-2.0.2.dist-info}/top_level.txt +0 -0
pycleaner/verifier.py
ADDED
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
"""
|
|
2
|
+
pycleaner.verifier
|
|
3
|
+
==================
|
|
4
|
+
|
|
5
|
+
Proof-Carrying Differential Equivalence Verification Engine.
|
|
6
|
+
|
|
7
|
+
Validates source code transformations (Tier A: Proven, Tier B: Suggested, Tier C: Refused)
|
|
8
|
+
by dynamically fuzzing baseline and transformed callables in isolated worker processes
|
|
9
|
+
under deterministic input vectors.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import ast
|
|
15
|
+
import dataclasses
|
|
16
|
+
import enum
|
|
17
|
+
import inspect
|
|
18
|
+
import multiprocessing as mp
|
|
19
|
+
import random
|
|
20
|
+
import time
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class VerificationTier(enum.Enum):
|
|
25
|
+
TIER_A_PROVEN = "TIER_A_PROVEN"
|
|
26
|
+
TIER_B_SUGGESTED = "TIER_B_SUGGESTED"
|
|
27
|
+
TIER_C_REFUSED = "TIER_C_REFUSED"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclasses.dataclass(frozen=True)
|
|
31
|
+
class CounterExample:
|
|
32
|
+
callable_name: str
|
|
33
|
+
arguments: tuple[Any, ...]
|
|
34
|
+
keyword_arguments: dict[str, Any]
|
|
35
|
+
original_result: str | None
|
|
36
|
+
original_error: str | None
|
|
37
|
+
transformed_result: str | None
|
|
38
|
+
transformed_error: str | None
|
|
39
|
+
seed: int
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclasses.dataclass(frozen=True)
|
|
43
|
+
class ProofReceipt:
|
|
44
|
+
filepath: str
|
|
45
|
+
callable_name: str
|
|
46
|
+
tier: VerificationTier
|
|
47
|
+
iterations_run: int
|
|
48
|
+
seed: int
|
|
49
|
+
duration_ms: float
|
|
50
|
+
counterexample: CounterExample | None = None
|
|
51
|
+
reason: str = ""
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclasses.dataclass(frozen=True)
|
|
55
|
+
class ExecutionResult:
|
|
56
|
+
is_success: bool
|
|
57
|
+
return_repr: str | None = None
|
|
58
|
+
error_type: str | None = None
|
|
59
|
+
error_message: str | None = None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _worker_differential_fuzz(
|
|
63
|
+
orig_source: str,
|
|
64
|
+
trans_source: str,
|
|
65
|
+
callable_name: str,
|
|
66
|
+
inputs: list[tuple[tuple[Any, ...], dict[str, Any]]],
|
|
67
|
+
conn: Any,
|
|
68
|
+
) -> None:
|
|
69
|
+
"""Child process worker: executes differential equivalence loop across all synthesized inputs."""
|
|
70
|
+
try:
|
|
71
|
+
orig_ns: dict[str, Any] = {
|
|
72
|
+
"__name__": "__verifier__",
|
|
73
|
+
"__builtins__": __builtins__,
|
|
74
|
+
}
|
|
75
|
+
trans_ns: dict[str, Any] = {
|
|
76
|
+
"__name__": "__verifier__",
|
|
77
|
+
"__builtins__": __builtins__,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
orig_code = compile(
|
|
82
|
+
orig_source, "<orig_sandbox>", "exec"
|
|
83
|
+
) # nosec: B102 - intentionally isolated in worker process
|
|
84
|
+
exec(
|
|
85
|
+
orig_code, orig_ns
|
|
86
|
+
) # nosec: B102 - intentionally isolated in worker process
|
|
87
|
+
except BaseException as e:
|
|
88
|
+
conn.send(
|
|
89
|
+
{
|
|
90
|
+
"status": "unresolvable",
|
|
91
|
+
"reason": f"Original module execution failed in sandbox: {type(e).__name__}: {e}",
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
return
|
|
95
|
+
|
|
96
|
+
try:
|
|
97
|
+
trans_code = compile(
|
|
98
|
+
trans_source, "<trans_sandbox>", "exec"
|
|
99
|
+
) # nosec: B102 - intentionally isolated in worker process
|
|
100
|
+
exec(
|
|
101
|
+
trans_code, trans_ns
|
|
102
|
+
) # nosec: B102 - intentionally isolated in worker process
|
|
103
|
+
except BaseException as e:
|
|
104
|
+
conn.send(
|
|
105
|
+
{
|
|
106
|
+
"status": "unresolvable",
|
|
107
|
+
"reason": f"Transformed module execution failed in sandbox: {type(e).__name__}: {e}",
|
|
108
|
+
}
|
|
109
|
+
)
|
|
110
|
+
return
|
|
111
|
+
|
|
112
|
+
orig_fn = orig_ns.get(callable_name)
|
|
113
|
+
trans_fn = trans_ns.get(callable_name)
|
|
114
|
+
|
|
115
|
+
if not callable(orig_fn) or not callable(trans_fn):
|
|
116
|
+
conn.send(
|
|
117
|
+
{
|
|
118
|
+
"status": "unresolvable",
|
|
119
|
+
"reason": f"Callable '{callable_name}' not found or not callable in sandbox.",
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
for index, (args, kwargs) in enumerate(inputs):
|
|
125
|
+
try:
|
|
126
|
+
orig_res = orig_fn(*args, **kwargs)
|
|
127
|
+
orig_success = True
|
|
128
|
+
orig_repr = repr(orig_res)
|
|
129
|
+
orig_err_type = None
|
|
130
|
+
orig_err_msg = None
|
|
131
|
+
except BaseException as e:
|
|
132
|
+
orig_success = False
|
|
133
|
+
orig_repr = None
|
|
134
|
+
orig_err_type = type(e).__name__
|
|
135
|
+
orig_err_msg = str(e)
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
trans_res = trans_fn(*args, **kwargs)
|
|
139
|
+
trans_success = True
|
|
140
|
+
trans_repr = repr(trans_res)
|
|
141
|
+
trans_err_type = None
|
|
142
|
+
trans_err_msg = None
|
|
143
|
+
except BaseException as e:
|
|
144
|
+
trans_success = False
|
|
145
|
+
trans_repr = None
|
|
146
|
+
trans_err_type = type(e).__name__
|
|
147
|
+
trans_err_msg = str(e)
|
|
148
|
+
|
|
149
|
+
diverged = False
|
|
150
|
+
if orig_success != trans_success:
|
|
151
|
+
diverged = True
|
|
152
|
+
elif orig_success and trans_success:
|
|
153
|
+
if orig_repr != trans_repr:
|
|
154
|
+
diverged = True
|
|
155
|
+
else:
|
|
156
|
+
if orig_err_type != trans_err_type:
|
|
157
|
+
diverged = True
|
|
158
|
+
|
|
159
|
+
if diverged:
|
|
160
|
+
conn.send(
|
|
161
|
+
{
|
|
162
|
+
"status": "diverged",
|
|
163
|
+
"iteration": index + 1,
|
|
164
|
+
"args": args,
|
|
165
|
+
"kwargs": kwargs,
|
|
166
|
+
"orig_result": orig_repr,
|
|
167
|
+
"orig_error": orig_err_msg or orig_err_type,
|
|
168
|
+
"trans_result": trans_repr,
|
|
169
|
+
"trans_error": trans_err_msg or trans_err_type,
|
|
170
|
+
}
|
|
171
|
+
)
|
|
172
|
+
return
|
|
173
|
+
|
|
174
|
+
conn.send(
|
|
175
|
+
{
|
|
176
|
+
"status": "proven",
|
|
177
|
+
"iterations_run": len(inputs),
|
|
178
|
+
}
|
|
179
|
+
)
|
|
180
|
+
except BaseException as e:
|
|
181
|
+
try:
|
|
182
|
+
conn.send(
|
|
183
|
+
{
|
|
184
|
+
"status": "unresolvable",
|
|
185
|
+
"reason": f"Worker crashed: {type(e).__name__}: {e}",
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
except Exception:
|
|
189
|
+
pass # Suppress secondary exceptions if IPC pipe fails to send crash reason
|
|
190
|
+
finally:
|
|
191
|
+
try:
|
|
192
|
+
conn.close()
|
|
193
|
+
except Exception:
|
|
194
|
+
pass # Best-effort resource cleanup for IPC connection
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class DeterministicInputSynthesizer:
|
|
198
|
+
"""Synthesizes deterministic boundary values and typed inputs from inspect.Signature."""
|
|
199
|
+
|
|
200
|
+
def __init__(self, seed: int) -> None:
|
|
201
|
+
self.seed = seed
|
|
202
|
+
self._rng = random.Random(seed)
|
|
203
|
+
|
|
204
|
+
def generate_for_param(self, param: inspect.Parameter) -> Any:
|
|
205
|
+
annotation = param.annotation
|
|
206
|
+
|
|
207
|
+
if annotation is int or annotation == "int":
|
|
208
|
+
return self._rng.choice([0, 1, -1, 42, -999, 2**31 - 1, -(2**31)])
|
|
209
|
+
if annotation is float or annotation == "float":
|
|
210
|
+
return self._rng.choice(
|
|
211
|
+
[0.0, 1.0, -1.0, 3.14159, float("inf"), float("-inf")]
|
|
212
|
+
)
|
|
213
|
+
if annotation is str or annotation == "str":
|
|
214
|
+
return self._rng.choice(
|
|
215
|
+
["", "test", " ", "a" * 100, "\n\t", "null", "123", "utf8_🐍"]
|
|
216
|
+
)
|
|
217
|
+
if annotation is bool or annotation == "bool":
|
|
218
|
+
return self._rng.choice([True, False])
|
|
219
|
+
if (
|
|
220
|
+
annotation is list
|
|
221
|
+
or annotation == "list"
|
|
222
|
+
or getattr(annotation, "__origin__", None) is list
|
|
223
|
+
):
|
|
224
|
+
return self._rng.choice([[], [0], [1, 2, 3], ["a", "b"]])
|
|
225
|
+
if (
|
|
226
|
+
annotation is dict
|
|
227
|
+
or annotation == "dict"
|
|
228
|
+
or getattr(annotation, "__origin__", None) is dict
|
|
229
|
+
):
|
|
230
|
+
return self._rng.choice([{}, {"key": "value"}, {"0": 0}])
|
|
231
|
+
if (
|
|
232
|
+
annotation is tuple
|
|
233
|
+
or annotation == "tuple"
|
|
234
|
+
or getattr(annotation, "__origin__", None) is tuple
|
|
235
|
+
):
|
|
236
|
+
return self._rng.choice([(), (1,), (1, "a")])
|
|
237
|
+
if annotation is None or annotation is type(None):
|
|
238
|
+
return None
|
|
239
|
+
|
|
240
|
+
# Fallback for untyped or complex parameters: cycle through primitive boundaries
|
|
241
|
+
return self._rng.choice([0, "", None, [], {}, False, 1.0])
|
|
242
|
+
|
|
243
|
+
def generate_arguments(
|
|
244
|
+
self, sig: inspect.Signature
|
|
245
|
+
) -> tuple[tuple[Any, ...], dict[str, Any]]:
|
|
246
|
+
pos_args: list[Any] = []
|
|
247
|
+
kw_args: dict[str, Any] = {}
|
|
248
|
+
|
|
249
|
+
for param in sig.parameters.values():
|
|
250
|
+
if param.kind in (
|
|
251
|
+
inspect.Parameter.POSITIONAL_ONLY,
|
|
252
|
+
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
253
|
+
):
|
|
254
|
+
pos_args.append(self.generate_for_param(param))
|
|
255
|
+
elif param.kind == inspect.Parameter.KEYWORD_ONLY:
|
|
256
|
+
kw_args[param.name] = self.generate_for_param(param)
|
|
257
|
+
elif param.kind == inspect.Parameter.VAR_POSITIONAL:
|
|
258
|
+
pos_args.extend([self.generate_for_param(param) for _ in range(2)])
|
|
259
|
+
elif param.kind == inspect.Parameter.VAR_KEYWORD:
|
|
260
|
+
kw_args["extra_kw"] = self.generate_for_param(param)
|
|
261
|
+
|
|
262
|
+
return tuple(pos_args), kw_args
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class IsolatedDifferentialVerifier:
|
|
266
|
+
"""
|
|
267
|
+
Executes differential verification of source transformations in isolated processes.
|
|
268
|
+
Enforces time bounds, memory isolation, and determinism.
|
|
269
|
+
"""
|
|
270
|
+
|
|
271
|
+
def __init__(
|
|
272
|
+
self,
|
|
273
|
+
iterations: int = 100,
|
|
274
|
+
timeout_seconds: float = 2.0,
|
|
275
|
+
base_seed: int | None = None,
|
|
276
|
+
) -> None:
|
|
277
|
+
self.iterations = iterations
|
|
278
|
+
self.timeout_seconds = timeout_seconds
|
|
279
|
+
self.base_seed = base_seed if base_seed is not None else 1337
|
|
280
|
+
|
|
281
|
+
def _extract_signature_from_source(
|
|
282
|
+
self, source: str, callable_name: str
|
|
283
|
+
) -> inspect.Signature | None:
|
|
284
|
+
try:
|
|
285
|
+
tree = ast.parse(source)
|
|
286
|
+
for node in ast.walk(tree):
|
|
287
|
+
if (
|
|
288
|
+
isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
|
|
289
|
+
and node.name == callable_name
|
|
290
|
+
):
|
|
291
|
+
params: list[inspect.Parameter] = []
|
|
292
|
+
for arg in node.args.posonlyargs:
|
|
293
|
+
ann = (
|
|
294
|
+
ast.unparse(arg.annotation)
|
|
295
|
+
if arg.annotation
|
|
296
|
+
else inspect.Parameter.empty
|
|
297
|
+
)
|
|
298
|
+
params.append(
|
|
299
|
+
inspect.Parameter(
|
|
300
|
+
arg.arg,
|
|
301
|
+
inspect.Parameter.POSITIONAL_ONLY,
|
|
302
|
+
annotation=ann,
|
|
303
|
+
)
|
|
304
|
+
)
|
|
305
|
+
for arg in node.args.args:
|
|
306
|
+
ann = (
|
|
307
|
+
ast.unparse(arg.annotation)
|
|
308
|
+
if arg.annotation
|
|
309
|
+
else inspect.Parameter.empty
|
|
310
|
+
)
|
|
311
|
+
params.append(
|
|
312
|
+
inspect.Parameter(
|
|
313
|
+
arg.arg,
|
|
314
|
+
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
315
|
+
annotation=ann,
|
|
316
|
+
)
|
|
317
|
+
)
|
|
318
|
+
if node.args.vararg:
|
|
319
|
+
ann = (
|
|
320
|
+
ast.unparse(node.args.vararg.annotation)
|
|
321
|
+
if node.args.vararg.annotation
|
|
322
|
+
else inspect.Parameter.empty
|
|
323
|
+
)
|
|
324
|
+
params.append(
|
|
325
|
+
inspect.Parameter(
|
|
326
|
+
node.args.vararg.arg,
|
|
327
|
+
inspect.Parameter.VAR_POSITIONAL,
|
|
328
|
+
annotation=ann,
|
|
329
|
+
)
|
|
330
|
+
)
|
|
331
|
+
for arg in node.args.kwonlyargs:
|
|
332
|
+
ann = (
|
|
333
|
+
ast.unparse(arg.annotation)
|
|
334
|
+
if arg.annotation
|
|
335
|
+
else inspect.Parameter.empty
|
|
336
|
+
)
|
|
337
|
+
params.append(
|
|
338
|
+
inspect.Parameter(
|
|
339
|
+
arg.arg, inspect.Parameter.KEYWORD_ONLY, annotation=ann
|
|
340
|
+
)
|
|
341
|
+
)
|
|
342
|
+
if node.args.kwarg:
|
|
343
|
+
ann = (
|
|
344
|
+
ast.unparse(node.args.kwarg.annotation)
|
|
345
|
+
if node.args.kwarg.annotation
|
|
346
|
+
else inspect.Parameter.empty
|
|
347
|
+
)
|
|
348
|
+
params.append(
|
|
349
|
+
inspect.Parameter(
|
|
350
|
+
node.args.kwarg.arg,
|
|
351
|
+
inspect.Parameter.VAR_KEYWORD,
|
|
352
|
+
annotation=ann,
|
|
353
|
+
)
|
|
354
|
+
)
|
|
355
|
+
return inspect.Signature(parameters=params)
|
|
356
|
+
return None
|
|
357
|
+
except Exception:
|
|
358
|
+
return None
|
|
359
|
+
|
|
360
|
+
def verify_transformation(
|
|
361
|
+
self,
|
|
362
|
+
filepath: str,
|
|
363
|
+
original_source: str,
|
|
364
|
+
transformed_source: str,
|
|
365
|
+
target_callable: str,
|
|
366
|
+
) -> ProofReceipt:
|
|
367
|
+
start_time = time.perf_counter()
|
|
368
|
+
|
|
369
|
+
# Step 1: Pre-flight AST Syntax and Signature Extraction
|
|
370
|
+
try:
|
|
371
|
+
ast.parse(original_source)
|
|
372
|
+
ast.parse(transformed_source)
|
|
373
|
+
except SyntaxError as err:
|
|
374
|
+
return ProofReceipt(
|
|
375
|
+
filepath=filepath,
|
|
376
|
+
callable_name=target_callable,
|
|
377
|
+
tier=VerificationTier.TIER_C_REFUSED,
|
|
378
|
+
iterations_run=0,
|
|
379
|
+
seed=self.base_seed,
|
|
380
|
+
duration_ms=(time.perf_counter() - start_time) * 1000.0,
|
|
381
|
+
reason=f"Transformed source failed AST syntax parsing: {err}",
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
sig = self._extract_signature_from_source(original_source, target_callable)
|
|
385
|
+
if sig is None:
|
|
386
|
+
return ProofReceipt(
|
|
387
|
+
filepath=filepath,
|
|
388
|
+
callable_name=target_callable,
|
|
389
|
+
tier=VerificationTier.TIER_B_SUGGESTED,
|
|
390
|
+
iterations_run=0,
|
|
391
|
+
seed=self.base_seed,
|
|
392
|
+
duration_ms=(time.perf_counter() - start_time) * 1000.0,
|
|
393
|
+
reason="Callable could not be isolated for signature-guided dynamic execution.",
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
synthesizer = DeterministicInputSynthesizer(seed=self.base_seed)
|
|
397
|
+
inputs = [synthesizer.generate_arguments(sig) for _ in range(self.iterations)]
|
|
398
|
+
|
|
399
|
+
# Step 2: Isolated Process Execution via Pipe
|
|
400
|
+
ctx = mp.get_context("spawn")
|
|
401
|
+
parent_conn, child_conn = ctx.Pipe(duplex=False)
|
|
402
|
+
process = ctx.Process(
|
|
403
|
+
target=_worker_differential_fuzz,
|
|
404
|
+
args=(
|
|
405
|
+
original_source,
|
|
406
|
+
transformed_source,
|
|
407
|
+
target_callable,
|
|
408
|
+
inputs,
|
|
409
|
+
child_conn,
|
|
410
|
+
),
|
|
411
|
+
)
|
|
412
|
+
process.daemon = True
|
|
413
|
+
process.start()
|
|
414
|
+
child_conn.close()
|
|
415
|
+
|
|
416
|
+
has_data = parent_conn.poll(timeout=self.timeout_seconds)
|
|
417
|
+
if not has_data:
|
|
418
|
+
process.terminate()
|
|
419
|
+
process.join(timeout=0.2)
|
|
420
|
+
if process.is_alive() and hasattr(process, "kill"):
|
|
421
|
+
process.kill()
|
|
422
|
+
elapsed = (time.perf_counter() - start_time) * 1000.0
|
|
423
|
+
return ProofReceipt(
|
|
424
|
+
filepath=filepath,
|
|
425
|
+
callable_name=target_callable,
|
|
426
|
+
tier=VerificationTier.TIER_B_SUGGESTED,
|
|
427
|
+
iterations_run=0,
|
|
428
|
+
seed=self.base_seed,
|
|
429
|
+
duration_ms=elapsed,
|
|
430
|
+
reason=f"Execution exceeded timeout limit of {self.timeout_seconds}s",
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
try:
|
|
434
|
+
msg = parent_conn.recv()
|
|
435
|
+
except EOFError:
|
|
436
|
+
process.join(timeout=0.2)
|
|
437
|
+
elapsed = (time.perf_counter() - start_time) * 1000.0
|
|
438
|
+
return ProofReceipt(
|
|
439
|
+
filepath=filepath,
|
|
440
|
+
callable_name=target_callable,
|
|
441
|
+
tier=VerificationTier.TIER_B_SUGGESTED,
|
|
442
|
+
iterations_run=0,
|
|
443
|
+
seed=self.base_seed,
|
|
444
|
+
duration_ms=elapsed,
|
|
445
|
+
reason="Worker process terminated or closed pipe unexpectedly.",
|
|
446
|
+
)
|
|
447
|
+
finally:
|
|
448
|
+
parent_conn.close()
|
|
449
|
+
process.join(timeout=0.5)
|
|
450
|
+
|
|
451
|
+
elapsed = (time.perf_counter() - start_time) * 1000.0
|
|
452
|
+
|
|
453
|
+
if msg.get("status") == "diverged":
|
|
454
|
+
counterexample = CounterExample(
|
|
455
|
+
callable_name=target_callable,
|
|
456
|
+
arguments=msg["args"],
|
|
457
|
+
keyword_arguments=msg["kwargs"],
|
|
458
|
+
original_result=msg.get("orig_result"),
|
|
459
|
+
original_error=msg.get("orig_error"),
|
|
460
|
+
transformed_result=msg.get("trans_result"),
|
|
461
|
+
transformed_error=msg.get("trans_error"),
|
|
462
|
+
seed=self.base_seed + msg["iteration"] - 1,
|
|
463
|
+
)
|
|
464
|
+
return ProofReceipt(
|
|
465
|
+
filepath=filepath,
|
|
466
|
+
callable_name=target_callable,
|
|
467
|
+
tier=VerificationTier.TIER_C_REFUSED,
|
|
468
|
+
iterations_run=msg["iteration"],
|
|
469
|
+
seed=self.base_seed,
|
|
470
|
+
duration_ms=elapsed,
|
|
471
|
+
counterexample=counterexample,
|
|
472
|
+
reason=f"Behavioral divergence detected on input iteration {msg['iteration']}.",
|
|
473
|
+
)
|
|
474
|
+
elif msg.get("status") == "proven":
|
|
475
|
+
return ProofReceipt(
|
|
476
|
+
filepath=filepath,
|
|
477
|
+
callable_name=target_callable,
|
|
478
|
+
tier=VerificationTier.TIER_A_PROVEN,
|
|
479
|
+
iterations_run=msg.get("iterations_run", self.iterations),
|
|
480
|
+
seed=self.base_seed,
|
|
481
|
+
duration_ms=elapsed,
|
|
482
|
+
reason=f"Proved invariant-preserving across {self.iterations} synthesized input permutations.",
|
|
483
|
+
)
|
|
484
|
+
else:
|
|
485
|
+
return ProofReceipt(
|
|
486
|
+
filepath=filepath,
|
|
487
|
+
callable_name=target_callable,
|
|
488
|
+
tier=VerificationTier.TIER_B_SUGGESTED,
|
|
489
|
+
iterations_run=0,
|
|
490
|
+
seed=self.base_seed,
|
|
491
|
+
duration_ms=elapsed,
|
|
492
|
+
reason=msg.get(
|
|
493
|
+
"reason", "Callable could not be verified dynamically in sandbox."
|
|
494
|
+
),
|
|
495
|
+
)
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
ballpython/__init__.py,sha256=d8ONxgaz9jml_fHPVvg867Vt5jGRhGTqzWPtux3WJOc,206
|
|
2
|
-
ballpython/__main__.py,sha256=aCRr0vnZfKYHDrPHBsYSjX5xTxtFJpTTSPVUSZTBK-I,136
|
|
3
|
-
ballpython/cli.py,sha256=LllCLRAQQ-fRR_lIXwmd2e3Q7DLCIvf-5jHBXsAhJWs,125
|
|
4
|
-
pycleaner/__init__.py,sha256=MfmUvfwNaguO_pYaRVKYAXHHKYgPpZmc6n0DPEzMOXA,1940
|
|
5
|
-
pycleaner/__main__.py,sha256=8QBFrPyxId563F6cipPMNVEBTG8TIZUgxQfp8gk1VSI,135
|
|
6
|
-
pycleaner/cli.py,sha256=1lmOLOiQz7AEABcV2WwcS_5UHkfaSlyjSqX-KHz64tg,50779
|
|
7
|
-
pycleaner/complexity_analyzer.py,sha256=esmBAwoC5XDgTKG_HVIXu82kFnJw6LYdbNJIShueSV8,15176
|
|
8
|
-
pycleaner/config.py,sha256=Mcp_1uTkIvxQtKKD1Y1xZeUmQVaHKf9PmqB6mqmMzCc,8401
|
|
9
|
-
pycleaner/dead_code_detector.py,sha256=yIa_RRCWyQMZLGweJsl41MGbqDE_j0teXoFW5ir8uNE,17598
|
|
10
|
-
pycleaner/dependency_auditor.py,sha256=wep0KcLYpHPy0bnuunMgkaIA9HODHTH6WQ8UhSX8oAQ,11589
|
|
11
|
-
pycleaner/import_resolver.py,sha256=JnAysZeYtXlmmM0LEnb9HBdkHnEsNwwp4QlxebRxGNE,32189
|
|
12
|
-
pycleaner/linter_formatter.py,sha256=LB5j66OCASU8WG8QgRFpSX7C2c7_UNMBgkJh2hSWxAY,20857
|
|
13
|
-
pycleaner/pipeline.py,sha256=o9rQUF4Jf8pcLicCPvAjAYHUTgCSAs2rzo_3FM8U-kY,12753
|
|
14
|
-
pycleaner/security_scanner.py,sha256=Ycz61UEuvSXcBZ49p5RwQXnBzS7x4NJMCrK8pWZeJBY,20630
|
|
15
|
-
pycleaner/syntax_healer.py,sha256=5yJ2WHjHjZ4i_046Xu_F5syDixf4J69ZrlofUHBVeXw,19823
|
|
16
|
-
pycleaner/taint_engine.py,sha256=bQc_nT63SgTMKIr7YsgbpW3USRNmw33AUiclzGlqb3c,26483
|
|
17
|
-
pycleaner/test_generator.py,sha256=Nu2i7qZtMZHz30h7lk-tef3VT-jAI6m4_jyheo2Abh0,16127
|
|
18
|
-
pycleaner/type_checker.py,sha256=CgnYRBTxDCaj2isGaFUdZQb0YxIATrEpElgSTg-Hwgc,33793
|
|
19
|
-
pycleaner/typeshed_resolver.py,sha256=N-kWU_CI5DG59lQMkt7wMW9sHYjNCBdfFS42b4y2Kr4,12742
|
|
20
|
-
ballpython-2.0.0.dist-info/METADATA,sha256=_gm1hvFBL42IWw8wkloJ7XJ7GWg2bxs4c2mUy6B_sRM,11728
|
|
21
|
-
ballpython-2.0.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
22
|
-
ballpython-2.0.0.dist-info/entry_points.txt,sha256=6ux-5UxoVSmlK5p9M-GDVt24sCdwTQq9wgRDkpMIYU8,81
|
|
23
|
-
ballpython-2.0.0.dist-info/top_level.txt,sha256=u6lmy8RWZ_saxCZAQTL7EijB4sunegOiVyk5fHjpwLk,21
|
|
24
|
-
ballpython-2.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|