diffai-python 0.3.5__py3-none-win_amd64.whl → 0.3.7__py3-none-win_amd64.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.
- {diffai_python-0.3.5.data → diffai_python-0.3.7.data}/scripts/diffai.exe +0 -0
- {diffai_python-0.3.5.dist-info → diffai_python-0.3.7.dist-info}/METADATA +1 -1
- diffai_python-0.3.7.dist-info/RECORD +4 -0
- diffai/__init__.py +0 -303
- diffai/__main__.py +0 -8
- diffai/installer.py +0 -206
- diffai_python-0.3.5.dist-info/RECORD +0 -7
- {diffai_python-0.3.5.dist-info → diffai_python-0.3.7.dist-info}/WHEEL +0 -0
|
Binary file
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
diffai_python-0.3.7.data/scripts/diffai.exe,sha256=IfN13u0-0p1KGYbLrO6-N-Bp-Sj1px9d4hIoC1j-liQ,243200
|
|
2
|
+
diffai_python-0.3.7.dist-info/METADATA,sha256=nd4DnAwMa5Uo3l-kkj2wQ03X9G4BPuEAKLPAPuCcdx8,11943
|
|
3
|
+
diffai_python-0.3.7.dist-info/WHEEL,sha256=T1-x9ZAB-aE3ewIGbYuockW5ywV7fI-Nla9FsiR1vW4,93
|
|
4
|
+
diffai_python-0.3.7.dist-info/RECORD,,
|
diffai/__init__.py
DELETED
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
diffai - AI/ML specialized diff tool for deep tensor comparison and analysis
|
|
3
|
-
|
|
4
|
-
This package provides a Python wrapper around the diffai Rust binary,
|
|
5
|
-
following the same pattern as ruff for optimal performance and reliability.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
# No backward compatibility imports
|
|
9
|
-
|
|
10
|
-
import json
|
|
11
|
-
import subprocess
|
|
12
|
-
import sys
|
|
13
|
-
import shutil
|
|
14
|
-
from pathlib import Path
|
|
15
|
-
from typing import Any, Dict, List, Optional, Union
|
|
16
|
-
from dataclasses import dataclass
|
|
17
|
-
from enum import Enum
|
|
18
|
-
|
|
19
|
-
# Version is now managed dynamically from pyproject.toml
|
|
20
|
-
# This prevents hardcoded version mismatches during releases
|
|
21
|
-
try:
|
|
22
|
-
from importlib.metadata import version
|
|
23
|
-
__version__ = version("diffai-python")
|
|
24
|
-
except ImportError:
|
|
25
|
-
# Fallback for Python < 3.8
|
|
26
|
-
try:
|
|
27
|
-
import pkg_resources
|
|
28
|
-
__version__ = pkg_resources.get_distribution("diffai-python").version
|
|
29
|
-
except Exception:
|
|
30
|
-
__version__ = "unknown"
|
|
31
|
-
|
|
32
|
-
class OutputFormat(Enum):
|
|
33
|
-
"""Supported output formats for diffai results."""
|
|
34
|
-
CLI = "cli"
|
|
35
|
-
JSON = "json"
|
|
36
|
-
YAML = "yaml"
|
|
37
|
-
|
|
38
|
-
@dataclass
|
|
39
|
-
class DiffOptions:
|
|
40
|
-
"""Configuration options for diffai analysis."""
|
|
41
|
-
|
|
42
|
-
# Basic options
|
|
43
|
-
input_format: Optional[str] = None
|
|
44
|
-
output_format: Optional[OutputFormat] = None
|
|
45
|
-
recursive: bool = False
|
|
46
|
-
verbose: bool = False
|
|
47
|
-
path: Optional[str] = None
|
|
48
|
-
ignore_keys_regex: Optional[str] = None
|
|
49
|
-
epsilon: Optional[float] = None
|
|
50
|
-
array_id_key: Optional[str] = None
|
|
51
|
-
|
|
52
|
-
# ML analysis options
|
|
53
|
-
show_layer_impact: bool = False
|
|
54
|
-
quantization_analysis: bool = False
|
|
55
|
-
sort_by_change_magnitude: bool = False
|
|
56
|
-
stats: bool = False
|
|
57
|
-
learning_progress: bool = False
|
|
58
|
-
convergence_analysis: bool = False
|
|
59
|
-
anomaly_detection: bool = False
|
|
60
|
-
gradient_analysis: bool = False
|
|
61
|
-
memory_analysis: bool = False
|
|
62
|
-
inference_speed_estimate: bool = False
|
|
63
|
-
regression_test: bool = False
|
|
64
|
-
alert_on_degradation: bool = False
|
|
65
|
-
review_friendly: bool = False
|
|
66
|
-
change_summary: bool = False
|
|
67
|
-
deployment_readiness: bool = False
|
|
68
|
-
architecture_comparison: bool = False
|
|
69
|
-
param_efficiency_analysis: bool = False
|
|
70
|
-
hyperparameter_impact: bool = False
|
|
71
|
-
learning_rate_analysis: bool = False
|
|
72
|
-
performance_impact_estimate: bool = False
|
|
73
|
-
generate_report: bool = False
|
|
74
|
-
markdown_output: bool = False
|
|
75
|
-
include_charts: bool = False
|
|
76
|
-
embedding_analysis: bool = False
|
|
77
|
-
similarity_matrix: bool = False
|
|
78
|
-
clustering_change: bool = False
|
|
79
|
-
attention_analysis: bool = False
|
|
80
|
-
head_importance: bool = False
|
|
81
|
-
attention_pattern_diff: bool = False
|
|
82
|
-
hyperparameter_comparison: bool = False
|
|
83
|
-
learning_curve_analysis: bool = False
|
|
84
|
-
statistical_significance: bool = False
|
|
85
|
-
|
|
86
|
-
def to_args(self) -> List[str]:
|
|
87
|
-
"""Convert options to command line arguments."""
|
|
88
|
-
args = []
|
|
89
|
-
|
|
90
|
-
# Basic options
|
|
91
|
-
if self.input_format:
|
|
92
|
-
args.extend(["--format", self.input_format])
|
|
93
|
-
if self.output_format:
|
|
94
|
-
args.extend(["--output", self.output_format.value])
|
|
95
|
-
if self.recursive:
|
|
96
|
-
args.append("--recursive")
|
|
97
|
-
if self.verbose:
|
|
98
|
-
args.append("--verbose")
|
|
99
|
-
if self.path:
|
|
100
|
-
args.extend(["--path", self.path])
|
|
101
|
-
if self.ignore_keys_regex:
|
|
102
|
-
args.extend(["--ignore-keys-regex", self.ignore_keys_regex])
|
|
103
|
-
if self.epsilon is not None:
|
|
104
|
-
args.extend(["--epsilon", str(self.epsilon)])
|
|
105
|
-
if self.array_id_key:
|
|
106
|
-
args.extend(["--array-id-key", self.array_id_key])
|
|
107
|
-
|
|
108
|
-
# ML analysis options
|
|
109
|
-
if self.show_layer_impact:
|
|
110
|
-
args.append("--show-layer-impact")
|
|
111
|
-
if self.quantization_analysis:
|
|
112
|
-
args.append("--quantization-analysis")
|
|
113
|
-
if self.sort_by_change_magnitude:
|
|
114
|
-
args.append("--sort-by-change-magnitude")
|
|
115
|
-
if self.stats:
|
|
116
|
-
args.append("--stats")
|
|
117
|
-
if self.learning_progress:
|
|
118
|
-
args.append("--learning-progress")
|
|
119
|
-
if self.convergence_analysis:
|
|
120
|
-
args.append("--convergence-analysis")
|
|
121
|
-
if self.anomaly_detection:
|
|
122
|
-
args.append("--anomaly-detection")
|
|
123
|
-
if self.gradient_analysis:
|
|
124
|
-
args.append("--gradient-analysis")
|
|
125
|
-
if self.memory_analysis:
|
|
126
|
-
args.append("--memory-analysis")
|
|
127
|
-
if self.inference_speed_estimate:
|
|
128
|
-
args.append("--inference-speed-estimate")
|
|
129
|
-
if self.regression_test:
|
|
130
|
-
args.append("--regression-test")
|
|
131
|
-
if self.alert_on_degradation:
|
|
132
|
-
args.append("--alert-on-degradation")
|
|
133
|
-
if self.review_friendly:
|
|
134
|
-
args.append("--review-friendly")
|
|
135
|
-
if self.change_summary:
|
|
136
|
-
args.append("--change-summary")
|
|
137
|
-
if self.deployment_readiness:
|
|
138
|
-
args.append("--deployment-readiness")
|
|
139
|
-
if self.architecture_comparison:
|
|
140
|
-
args.append("--architecture-comparison")
|
|
141
|
-
if self.param_efficiency_analysis:
|
|
142
|
-
args.append("--param-efficiency-analysis")
|
|
143
|
-
if self.hyperparameter_impact:
|
|
144
|
-
args.append("--hyperparameter-impact")
|
|
145
|
-
if self.learning_rate_analysis:
|
|
146
|
-
args.append("--learning-rate-analysis")
|
|
147
|
-
if self.performance_impact_estimate:
|
|
148
|
-
args.append("--performance-impact-estimate")
|
|
149
|
-
if self.generate_report:
|
|
150
|
-
args.append("--generate-report")
|
|
151
|
-
if self.markdown_output:
|
|
152
|
-
args.append("--markdown-output")
|
|
153
|
-
if self.include_charts:
|
|
154
|
-
args.append("--include-charts")
|
|
155
|
-
if self.embedding_analysis:
|
|
156
|
-
args.append("--embedding-analysis")
|
|
157
|
-
if self.similarity_matrix:
|
|
158
|
-
args.append("--similarity-matrix")
|
|
159
|
-
if self.clustering_change:
|
|
160
|
-
args.append("--clustering-change")
|
|
161
|
-
if self.attention_analysis:
|
|
162
|
-
args.append("--attention-analysis")
|
|
163
|
-
if self.head_importance:
|
|
164
|
-
args.append("--head-importance")
|
|
165
|
-
if self.attention_pattern_diff:
|
|
166
|
-
args.append("--attention-pattern-diff")
|
|
167
|
-
if self.hyperparameter_comparison:
|
|
168
|
-
args.append("--hyperparameter-comparison")
|
|
169
|
-
if self.learning_curve_analysis:
|
|
170
|
-
args.append("--learning-curve-analysis")
|
|
171
|
-
if self.statistical_significance:
|
|
172
|
-
args.append("--statistical-significance")
|
|
173
|
-
|
|
174
|
-
return args
|
|
175
|
-
|
|
176
|
-
class DiffaiError(Exception):
|
|
177
|
-
"""Base exception for diffai-related errors."""
|
|
178
|
-
pass
|
|
179
|
-
|
|
180
|
-
class DiffResult:
|
|
181
|
-
"""Result from diffai analysis."""
|
|
182
|
-
|
|
183
|
-
def __init__(self, raw_output: str, format_type: str = "cli", return_code: int = 0):
|
|
184
|
-
self.raw_output = raw_output
|
|
185
|
-
self.format_type = format_type
|
|
186
|
-
self.return_code = return_code
|
|
187
|
-
self._parsed_data = None
|
|
188
|
-
|
|
189
|
-
@property
|
|
190
|
-
def data(self) -> Any:
|
|
191
|
-
"""Get parsed data (JSON objects for JSON output, raw string otherwise)."""
|
|
192
|
-
if self._parsed_data is None:
|
|
193
|
-
if self.format_type == "json" and self.raw_output.strip():
|
|
194
|
-
try:
|
|
195
|
-
self._parsed_data = json.loads(self.raw_output)
|
|
196
|
-
except json.JSONDecodeError:
|
|
197
|
-
self._parsed_data = self.raw_output
|
|
198
|
-
else:
|
|
199
|
-
self._parsed_data = self.raw_output
|
|
200
|
-
return self._parsed_data
|
|
201
|
-
|
|
202
|
-
@property
|
|
203
|
-
def is_json(self) -> bool:
|
|
204
|
-
"""True if result is in JSON format."""
|
|
205
|
-
return self.format_type == "json" and isinstance(self.data, (dict, list))
|
|
206
|
-
|
|
207
|
-
def __str__(self) -> str:
|
|
208
|
-
return self.raw_output
|
|
209
|
-
|
|
210
|
-
def _find_diffai_binary() -> str:
|
|
211
|
-
"""Find the diffai binary, checking bundled location first."""
|
|
212
|
-
# Check if bundled with package
|
|
213
|
-
package_dir = Path(__file__).parent.parent.parent
|
|
214
|
-
bundled_binary = package_dir / "diffai"
|
|
215
|
-
|
|
216
|
-
if bundled_binary.exists() and bundled_binary.is_file():
|
|
217
|
-
return str(bundled_binary)
|
|
218
|
-
|
|
219
|
-
# Fallback to system PATH
|
|
220
|
-
system_binary = shutil.which("diffai")
|
|
221
|
-
if system_binary:
|
|
222
|
-
return system_binary
|
|
223
|
-
|
|
224
|
-
raise DiffaiError(
|
|
225
|
-
"diffai binary not found. Please ensure diffai is installed or available in PATH."
|
|
226
|
-
)
|
|
227
|
-
|
|
228
|
-
def diff(
|
|
229
|
-
input1: str,
|
|
230
|
-
input2: str,
|
|
231
|
-
options: Optional[Union[DiffOptions, Dict[str, Any]]] = None,
|
|
232
|
-
**kwargs
|
|
233
|
-
) -> DiffResult:
|
|
234
|
-
"""
|
|
235
|
-
Compare two files using diffai.
|
|
236
|
-
|
|
237
|
-
Args:
|
|
238
|
-
input1: Path to first input file
|
|
239
|
-
input2: Path to second input file
|
|
240
|
-
options: DiffOptions object or dict of options
|
|
241
|
-
**kwargs: Additional options as keyword arguments
|
|
242
|
-
|
|
243
|
-
Returns:
|
|
244
|
-
DiffResult object containing comparison results
|
|
245
|
-
"""
|
|
246
|
-
# Handle different option formats
|
|
247
|
-
if options is None:
|
|
248
|
-
options = DiffOptions(**kwargs)
|
|
249
|
-
elif isinstance(options, dict):
|
|
250
|
-
combined_options = {**options, **kwargs}
|
|
251
|
-
options = DiffOptions(**combined_options)
|
|
252
|
-
elif kwargs:
|
|
253
|
-
# Merge kwargs into existing DiffOptions
|
|
254
|
-
option_dict = {
|
|
255
|
-
field.name: getattr(options, field.name)
|
|
256
|
-
for field in options.__dataclass_fields__.values()
|
|
257
|
-
}
|
|
258
|
-
combined_options = {**option_dict, **kwargs}
|
|
259
|
-
options = DiffOptions(**combined_options)
|
|
260
|
-
|
|
261
|
-
try:
|
|
262
|
-
binary_path = _find_diffai_binary()
|
|
263
|
-
cmd = [binary_path] + options.to_args() + [input1, input2]
|
|
264
|
-
|
|
265
|
-
result = subprocess.run(
|
|
266
|
-
cmd,
|
|
267
|
-
capture_output=True,
|
|
268
|
-
text=True,
|
|
269
|
-
check=False
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
if result.returncode != 0 and result.stderr:
|
|
273
|
-
raise DiffaiError(f"diffai failed: {result.stderr}")
|
|
274
|
-
|
|
275
|
-
format_type = options.output_format.value if options.output_format else "cli"
|
|
276
|
-
return DiffResult(result.stdout, format_type, result.returncode)
|
|
277
|
-
|
|
278
|
-
except FileNotFoundError:
|
|
279
|
-
raise DiffaiError("diffai binary not found")
|
|
280
|
-
except Exception as e:
|
|
281
|
-
raise DiffaiError(f"Diff failed: {e}")
|
|
282
|
-
|
|
283
|
-
def main():
|
|
284
|
-
"""CLI entry point for the diffai command."""
|
|
285
|
-
try:
|
|
286
|
-
binary_path = _find_diffai_binary()
|
|
287
|
-
# Forward all arguments to the binary
|
|
288
|
-
result = subprocess.run([binary_path] + sys.argv[1:])
|
|
289
|
-
sys.exit(result.returncode)
|
|
290
|
-
except DiffaiError as e:
|
|
291
|
-
print(f"Error: {e}", file=sys.stderr)
|
|
292
|
-
sys.exit(1)
|
|
293
|
-
|
|
294
|
-
# Export main API
|
|
295
|
-
__all__ = [
|
|
296
|
-
"diff",
|
|
297
|
-
"DiffOptions",
|
|
298
|
-
"DiffResult",
|
|
299
|
-
"OutputFormat",
|
|
300
|
-
"DiffaiError",
|
|
301
|
-
"__version__",
|
|
302
|
-
"main",
|
|
303
|
-
]
|
diffai/__main__.py
DELETED
diffai/installer.py
DELETED
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Binary installer for diffai Python package.
|
|
3
|
-
|
|
4
|
-
This module handles downloading and installing the diffai binary
|
|
5
|
-
when the package is installed via pip.
|
|
6
|
-
|
|
7
|
-
Supports platforms: Windows, Linux, Darwin (macOS) with x86_64 and aarch64 architectures.
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
import os
|
|
11
|
-
import platform
|
|
12
|
-
import shutil
|
|
13
|
-
import subprocess
|
|
14
|
-
import sys
|
|
15
|
-
import tarfile
|
|
16
|
-
import tempfile
|
|
17
|
-
import urllib.request
|
|
18
|
-
import zipfile
|
|
19
|
-
from pathlib import Path
|
|
20
|
-
|
|
21
|
-
# Package version constant for GitHub releases
|
|
22
|
-
PACKAGE_VERSION = "0.3.4"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def get_platform_info():
|
|
26
|
-
"""Get platform-specific information for binary download.
|
|
27
|
-
|
|
28
|
-
Supported platforms: Windows, Linux, Darwin
|
|
29
|
-
Supported architectures: x86_64, aarch64
|
|
30
|
-
"""
|
|
31
|
-
system = platform.system().lower()
|
|
32
|
-
machine = platform.machine().lower()
|
|
33
|
-
|
|
34
|
-
if system == "linux": # Linux systems
|
|
35
|
-
if machine in ("x86_64", "amd64"):
|
|
36
|
-
return "linux-x86_64", "diffai"
|
|
37
|
-
else:
|
|
38
|
-
raise RuntimeError(f"Unsupported Linux architecture: {machine}")
|
|
39
|
-
elif system == "darwin": # Darwin (macOS) systems
|
|
40
|
-
if machine == "arm64":
|
|
41
|
-
return "macos-aarch64", "diffai"
|
|
42
|
-
elif machine in ("x86_64", "amd64"):
|
|
43
|
-
return "macos-x86_64", "diffai"
|
|
44
|
-
else:
|
|
45
|
-
raise RuntimeError(f"Unsupported Darwin architecture: {machine}")
|
|
46
|
-
elif system == "windows": # Windows systems
|
|
47
|
-
if machine in ("x86_64", "amd64"):
|
|
48
|
-
return "windows-x86_64", "diffai.exe"
|
|
49
|
-
else:
|
|
50
|
-
raise RuntimeError(f"Unsupported Windows architecture: {machine}")
|
|
51
|
-
else:
|
|
52
|
-
raise RuntimeError(f"Unsupported operating system: {system}")
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def download_file(url, dest_path):
|
|
56
|
-
"""Download a file from URL to destination path."""
|
|
57
|
-
try:
|
|
58
|
-
with urllib.request.urlopen(url) as response:
|
|
59
|
-
with open(dest_path, 'wb') as f:
|
|
60
|
-
f.write(response.read())
|
|
61
|
-
except Exception as e:
|
|
62
|
-
raise RuntimeError(f"Failed to download file: {e}")
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def extract_archive(archive_path, extract_to):
|
|
66
|
-
"""Extract archive file to destination directory."""
|
|
67
|
-
try:
|
|
68
|
-
if archive_path.endswith('.zip'):
|
|
69
|
-
with zipfile.ZipFile(archive_path, 'r') as zip_ref:
|
|
70
|
-
zip_ref.extractall(extract_to)
|
|
71
|
-
elif archive_path.endswith(('.tar.gz', '.tgz')):
|
|
72
|
-
with tarfile.open(archive_path, 'r:gz') as tar_ref:
|
|
73
|
-
tar_ref.extractall(extract_to)
|
|
74
|
-
else:
|
|
75
|
-
raise RuntimeError(f"Unsupported archive format: {archive_path}")
|
|
76
|
-
except Exception as e:
|
|
77
|
-
raise RuntimeError(f"Failed to extract archive: {e}")
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def verify_binary(binary_path):
|
|
81
|
-
"""Verify that the downloaded binary works correctly."""
|
|
82
|
-
try:
|
|
83
|
-
# Test binary with --version flag
|
|
84
|
-
result = subprocess.run(
|
|
85
|
-
[binary_path, "--version"],
|
|
86
|
-
capture_output=True,
|
|
87
|
-
text=True,
|
|
88
|
-
timeout=10
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
if result.returncode == 0:
|
|
92
|
-
return True
|
|
93
|
-
else:
|
|
94
|
-
raise RuntimeError(f"Binary verification failed: {result.stderr}")
|
|
95
|
-
|
|
96
|
-
except subprocess.TimeoutExpired:
|
|
97
|
-
raise RuntimeError("Binary verification timed out")
|
|
98
|
-
except Exception as e:
|
|
99
|
-
raise RuntimeError(f"Failed to verify binary: {e}")
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
def get_latest_release_info():
|
|
103
|
-
"""Get information about the latest GitHub release from github.com."""
|
|
104
|
-
try:
|
|
105
|
-
import json
|
|
106
|
-
|
|
107
|
-
# GitHub API URL for latest release
|
|
108
|
-
url = "https://api.github.com/repos/kako-jun/diffai/releases/latest"
|
|
109
|
-
with urllib.request.urlopen(url) as response:
|
|
110
|
-
data = json.loads(response.read().decode())
|
|
111
|
-
|
|
112
|
-
return data["tag_name"], data["assets"]
|
|
113
|
-
except Exception as e:
|
|
114
|
-
raise RuntimeError(f"Failed to get release information from github.com: {e}")
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
def download_binary(version=None):
|
|
118
|
-
"""Download the diffai binary for the current platform."""
|
|
119
|
-
platform_name, binary_name = get_platform_info()
|
|
120
|
-
|
|
121
|
-
if version is None:
|
|
122
|
-
version, assets = get_latest_release_info()
|
|
123
|
-
else:
|
|
124
|
-
# For specific version, construct asset URL manually
|
|
125
|
-
assets = None
|
|
126
|
-
|
|
127
|
-
# Construct download URL
|
|
128
|
-
if assets:
|
|
129
|
-
# Find the correct asset
|
|
130
|
-
asset_name = f"diffai-{platform_name}.tar.gz"
|
|
131
|
-
if platform_name.startswith("windows"):
|
|
132
|
-
asset_name = f"diffai-{platform_name}.zip"
|
|
133
|
-
|
|
134
|
-
asset_url = None
|
|
135
|
-
for asset in assets:
|
|
136
|
-
if asset["name"] == asset_name:
|
|
137
|
-
asset_url = asset["browser_download_url"]
|
|
138
|
-
break
|
|
139
|
-
|
|
140
|
-
if not asset_url:
|
|
141
|
-
raise RuntimeError(f"Binary not found for platform: {platform_name}")
|
|
142
|
-
else:
|
|
143
|
-
# Fallback URL construction
|
|
144
|
-
base_url = "https://github.com/kako-jun/diffai/releases/download"
|
|
145
|
-
if platform_name.startswith("windows"):
|
|
146
|
-
asset_name = f"diffai-{platform_name}.zip"
|
|
147
|
-
else:
|
|
148
|
-
asset_name = f"diffai-{platform_name}.tar.gz"
|
|
149
|
-
asset_url = f"{base_url}/{version}/{asset_name}"
|
|
150
|
-
|
|
151
|
-
# Download to temporary location
|
|
152
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
|
153
|
-
temp_path = Path(temp_dir)
|
|
154
|
-
archive_path = temp_path / asset_name
|
|
155
|
-
|
|
156
|
-
print(f"Downloading {asset_url}...")
|
|
157
|
-
urllib.request.urlretrieve(asset_url, archive_path)
|
|
158
|
-
|
|
159
|
-
# Extract archive
|
|
160
|
-
if asset_name.endswith(".tar.gz"):
|
|
161
|
-
subprocess.run(["tar", "-xzf", archive_path, "-C", temp_path], check=True)
|
|
162
|
-
elif asset_name.endswith(".zip"):
|
|
163
|
-
import zipfile
|
|
164
|
-
with zipfile.ZipFile(archive_path, 'r') as zip_ref:
|
|
165
|
-
zip_ref.extractall(temp_path)
|
|
166
|
-
|
|
167
|
-
# Find the binary
|
|
168
|
-
binary_path = temp_path / binary_name
|
|
169
|
-
if not binary_path.exists():
|
|
170
|
-
raise RuntimeError(f"Binary not found in archive: {binary_name}")
|
|
171
|
-
|
|
172
|
-
return binary_path
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
def install_binary():
|
|
176
|
-
"""Install the diffai binary to the package directory."""
|
|
177
|
-
try:
|
|
178
|
-
# Get package directory
|
|
179
|
-
package_dir = Path(__file__).parent.parent.parent
|
|
180
|
-
binary_dir = package_dir / "bin"
|
|
181
|
-
binary_dir.mkdir(exist_ok=True)
|
|
182
|
-
|
|
183
|
-
# Download binary
|
|
184
|
-
temp_binary = download_binary()
|
|
185
|
-
|
|
186
|
-
# Copy to package directory
|
|
187
|
-
platform_name, binary_name = get_platform_info()
|
|
188
|
-
target_path = binary_dir / binary_name
|
|
189
|
-
|
|
190
|
-
shutil.copy2(temp_binary, target_path)
|
|
191
|
-
|
|
192
|
-
# Make executable on Unix-like systems
|
|
193
|
-
if not platform_name.startswith("windows"):
|
|
194
|
-
os.chmod(target_path, 0o755)
|
|
195
|
-
|
|
196
|
-
print(f"Successfully installed diffai binary to {target_path}")
|
|
197
|
-
return target_path
|
|
198
|
-
|
|
199
|
-
except Exception as e:
|
|
200
|
-
print(f"Warning: Failed to install diffai binary: {e}")
|
|
201
|
-
print("The Python API will still work if diffai is available in PATH")
|
|
202
|
-
return None
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
if __name__ == "__main__":
|
|
206
|
-
install_binary()
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
diffai/__init__.py,sha256=eL_ZqXdoct718oT9v7smtFVbvRSrV1WjP0w4oRNMnjs,10653
|
|
2
|
-
diffai/__main__.py,sha256=0ABdXiMt3e1FQ3Bept_jgjEoU6unvf-pW9iG50YuS70,106
|
|
3
|
-
diffai/installer.py,sha256=8aLhL6sZ8uDgCoZQM6Ea_dR2jiF4k7mN81I7TghO12U,7132
|
|
4
|
-
diffai_python-0.3.5.data/scripts/diffai.exe,sha256=l_nv72_RPvTHQ1MYsOYIxmLEep4Vcm0BPVAd_mF64ys,243200
|
|
5
|
-
diffai_python-0.3.5.dist-info/METADATA,sha256=5MP_ruae0bR2XXDYJSikQH6udsbO88onsZQ9N7jJ9r4,11943
|
|
6
|
-
diffai_python-0.3.5.dist-info/WHEEL,sha256=T1-x9ZAB-aE3ewIGbYuockW5ywV7fI-Nla9FsiR1vW4,93
|
|
7
|
-
diffai_python-0.3.5.dist-info/RECORD,,
|
|
File without changes
|