skylos 1.2.2__py3-none-any.whl → 2.1.0__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.
Potentially problematic release.
This version of skylos might be problematic. Click here for more details.
- skylos/__init__.py +1 -1
- skylos/analyzer.py +103 -121
- skylos/cli.py +66 -109
- skylos/codemods.py +89 -0
- skylos/constants.py +25 -10
- skylos/framework_aware.py +290 -90
- skylos/server.py +560 -0
- skylos/test_aware.py +0 -1
- skylos/visitor.py +249 -90
- {skylos-1.2.2.dist-info → skylos-2.1.0.dist-info}/METADATA +4 -1
- {skylos-1.2.2.dist-info → skylos-2.1.0.dist-info}/RECORD +16 -13
- test/test_codemods.py +153 -0
- test/test_framework_aware.py +176 -242
- {skylos-1.2.2.dist-info → skylos-2.1.0.dist-info}/WHEEL +0 -0
- {skylos-1.2.2.dist-info → skylos-2.1.0.dist-info}/entry_points.txt +0 -0
- {skylos-1.2.2.dist-info → skylos-2.1.0.dist-info}/top_level.txt +0 -0
skylos/server.py
ADDED
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Skylos Web Server
|
|
4
|
+
Serves the frontend and provides API to analyze projects using skylos
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from flask import Flask, request, jsonify
|
|
8
|
+
from flask_cors import CORS
|
|
9
|
+
import skylos
|
|
10
|
+
import json
|
|
11
|
+
import os
|
|
12
|
+
import webbrowser
|
|
13
|
+
from threading import Timer
|
|
14
|
+
|
|
15
|
+
app = Flask(__name__)
|
|
16
|
+
CORS(app)
|
|
17
|
+
|
|
18
|
+
@app.route('/')
|
|
19
|
+
def serve_frontend():
|
|
20
|
+
"""Serve the frontend HTML"""
|
|
21
|
+
return """<!DOCTYPE html>
|
|
22
|
+
<html lang="en">
|
|
23
|
+
<head>
|
|
24
|
+
<meta charset="UTF-8">
|
|
25
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
26
|
+
<title>Skylos Dead Code Analyzer</title>
|
|
27
|
+
<style>
|
|
28
|
+
* {
|
|
29
|
+
margin: 0;
|
|
30
|
+
padding: 0;
|
|
31
|
+
box-sizing: border-box;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
body {
|
|
35
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', sans-serif;
|
|
36
|
+
background: #000000;
|
|
37
|
+
color: #ffffff;
|
|
38
|
+
min-height: 100vh;
|
|
39
|
+
padding: 20px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.container {
|
|
43
|
+
max-width: 1400px;
|
|
44
|
+
margin: 0 auto;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.header {
|
|
48
|
+
text-align: center;
|
|
49
|
+
margin-bottom: 40px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.header h1 {
|
|
53
|
+
font-size: 3rem;
|
|
54
|
+
margin-bottom: 10px;
|
|
55
|
+
color: #ffffff;
|
|
56
|
+
font-weight: 300;
|
|
57
|
+
letter-spacing: -1px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.header p {
|
|
61
|
+
color: #888888;
|
|
62
|
+
font-size: 1.1rem;
|
|
63
|
+
margin-top: 10px;
|
|
64
|
+
font-weight: 400;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.controls {
|
|
68
|
+
background: #111111;
|
|
69
|
+
border: 1px solid #333333;
|
|
70
|
+
border-radius: 12px;
|
|
71
|
+
padding: 32px;
|
|
72
|
+
margin-bottom: 32px;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.folder-input {
|
|
76
|
+
margin-bottom: 25px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.folder-input label {
|
|
80
|
+
display: block;
|
|
81
|
+
font-weight: bold;
|
|
82
|
+
margin-bottom: 10px;
|
|
83
|
+
color: #ffffff;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.folder-input input {
|
|
87
|
+
width: 100%;
|
|
88
|
+
padding: 16px;
|
|
89
|
+
background: #222222;
|
|
90
|
+
color: #ffffff;
|
|
91
|
+
border: 1px solid #444444;
|
|
92
|
+
border-radius: 8px;
|
|
93
|
+
font-family: inherit;
|
|
94
|
+
font-size: 14px;
|
|
95
|
+
transition: border-color 0.2s ease;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.folder-input input:focus {
|
|
99
|
+
outline: none;
|
|
100
|
+
border-color: #ffffff;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.folder-input input::placeholder {
|
|
104
|
+
color: #888888;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.analyze-btn {
|
|
108
|
+
background: #ffffff;
|
|
109
|
+
color: #000000;
|
|
110
|
+
border: none;
|
|
111
|
+
padding: 16px 32px;
|
|
112
|
+
border-radius: 8px;
|
|
113
|
+
cursor: pointer;
|
|
114
|
+
font-weight: 500;
|
|
115
|
+
font-family: inherit;
|
|
116
|
+
font-size: 14px;
|
|
117
|
+
margin-right: 15px;
|
|
118
|
+
transition: all 0.2s ease;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.analyze-btn:hover {
|
|
122
|
+
background: #f0f0f0;
|
|
123
|
+
transform: translateY(-1px);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.analyze-btn:disabled {
|
|
127
|
+
background: #666666;
|
|
128
|
+
color: #ffffff;
|
|
129
|
+
cursor: not-allowed;
|
|
130
|
+
transform: none;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.confidence-control {
|
|
134
|
+
margin-top: 25px;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.confidence-control label {
|
|
138
|
+
display: block;
|
|
139
|
+
font-weight: bold;
|
|
140
|
+
margin-bottom: 10px;
|
|
141
|
+
color: #ffffff;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.confidence-slider {
|
|
145
|
+
width: 100%;
|
|
146
|
+
height: 6px;
|
|
147
|
+
background: #333333;
|
|
148
|
+
outline: none;
|
|
149
|
+
border-radius: 3px;
|
|
150
|
+
-webkit-appearance: none;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.confidence-slider::-webkit-slider-thumb {
|
|
154
|
+
-webkit-appearance: none;
|
|
155
|
+
appearance: none;
|
|
156
|
+
width: 20px;
|
|
157
|
+
height: 20px;
|
|
158
|
+
border-radius: 50%;
|
|
159
|
+
background: #ffffff;
|
|
160
|
+
cursor: pointer;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.confidence-slider::-moz-range-thumb {
|
|
164
|
+
width: 20px;
|
|
165
|
+
height: 20px;
|
|
166
|
+
border-radius: 50%;
|
|
167
|
+
background: #ffffff;
|
|
168
|
+
cursor: pointer;
|
|
169
|
+
border: none;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.summary {
|
|
173
|
+
background: #111111;
|
|
174
|
+
border: 1px solid #333333;
|
|
175
|
+
border-radius: 8px;
|
|
176
|
+
padding: 25px;
|
|
177
|
+
margin-bottom: 30px;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.summary h2 {
|
|
181
|
+
margin-bottom: 20px;
|
|
182
|
+
color: #ffffff;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.summary-grid {
|
|
186
|
+
display: grid;
|
|
187
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
188
|
+
gap: 15px;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.summary-item {
|
|
192
|
+
background: #222222;
|
|
193
|
+
border: 1px solid #444444;
|
|
194
|
+
border-radius: 4px;
|
|
195
|
+
padding: 15px;
|
|
196
|
+
text-align: center;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.summary-item .count {
|
|
200
|
+
font-size: 2rem;
|
|
201
|
+
font-weight: bold;
|
|
202
|
+
color: #ffffff;
|
|
203
|
+
margin-bottom: 5px;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.summary-item .label {
|
|
207
|
+
color: #cccccc;
|
|
208
|
+
text-transform: uppercase;
|
|
209
|
+
font-size: 0.9rem;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.results {
|
|
213
|
+
background: #111111;
|
|
214
|
+
border: 1px solid #333333;
|
|
215
|
+
border-radius: 8px;
|
|
216
|
+
padding: 25px;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.results h2 {
|
|
220
|
+
margin-bottom: 20px;
|
|
221
|
+
color: #ffffff;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.dead-code-list {
|
|
225
|
+
max-height: 600px;
|
|
226
|
+
overflow-y: auto;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.dead-code-item {
|
|
230
|
+
background: #222222;
|
|
231
|
+
border: 1px solid #444444;
|
|
232
|
+
border-radius: 4px;
|
|
233
|
+
padding: 15px;
|
|
234
|
+
margin-bottom: 10px;
|
|
235
|
+
display: flex;
|
|
236
|
+
justify-content: space-between;
|
|
237
|
+
align-items: center;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.item-details {
|
|
241
|
+
flex-grow: 1;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.item-name {
|
|
245
|
+
font-weight: bold;
|
|
246
|
+
color: #ffffff;
|
|
247
|
+
margin-bottom: 5px;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.item-location {
|
|
251
|
+
color: #999999;
|
|
252
|
+
font-size: 0.9rem;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.item-meta {
|
|
256
|
+
display: flex;
|
|
257
|
+
align-items: center;
|
|
258
|
+
gap: 10px;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.item-type {
|
|
262
|
+
background: #ffffff;
|
|
263
|
+
color: #000000;
|
|
264
|
+
padding: 6px 12px;
|
|
265
|
+
border-radius: 6px;
|
|
266
|
+
font-size: 0.8rem;
|
|
267
|
+
font-weight: 500;
|
|
268
|
+
text-transform: uppercase;
|
|
269
|
+
letter-spacing: 0.5px;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.item-confidence {
|
|
273
|
+
color: #ffffff;
|
|
274
|
+
font-weight: bold;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.no-results {
|
|
278
|
+
text-align: center;
|
|
279
|
+
padding: 40px;
|
|
280
|
+
color: #666666;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.loading {
|
|
284
|
+
text-align: center;
|
|
285
|
+
padding: 40px;
|
|
286
|
+
color: #ffffff;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.error {
|
|
290
|
+
background: #330000;
|
|
291
|
+
border: 1px solid #660000;
|
|
292
|
+
color: #ff6666;
|
|
293
|
+
padding: 15px;
|
|
294
|
+
border-radius: 4px;
|
|
295
|
+
margin-bottom: 20px;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
::-webkit-scrollbar {
|
|
299
|
+
width: 8px;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
::-webkit-scrollbar-track {
|
|
303
|
+
background: #222222;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
::-webkit-scrollbar-thumb {
|
|
307
|
+
background: #444444;
|
|
308
|
+
border-radius: 4px;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
::-webkit-scrollbar-thumb:hover {
|
|
312
|
+
background: #666666;
|
|
313
|
+
}
|
|
314
|
+
</style>
|
|
315
|
+
</head>
|
|
316
|
+
<body>
|
|
317
|
+
<div class="container">
|
|
318
|
+
<div class="header">
|
|
319
|
+
<h1>Skylos Dead Code Analyzer</h1>
|
|
320
|
+
<p>Find and eliminate unused code in your Python projects</p>
|
|
321
|
+
</div>
|
|
322
|
+
|
|
323
|
+
<div class="controls">
|
|
324
|
+
<div class="folder-input">
|
|
325
|
+
<label for="folderPath">Project Path:</label>
|
|
326
|
+
<input type="text" id="folderPath" placeholder="/path/to/your/python/project" value="./">
|
|
327
|
+
</div>
|
|
328
|
+
|
|
329
|
+
<button class="analyze-btn" id="analyzeBtn">Analyze Project</button>
|
|
330
|
+
|
|
331
|
+
<div class="confidence-control">
|
|
332
|
+
<label for="confidenceSlider">Confidence Threshold: <span id="confidenceValue">60</span>%</label>
|
|
333
|
+
<input type="range" id="confidenceSlider" class="confidence-slider"
|
|
334
|
+
min="0" max="100" value="60" step="1">
|
|
335
|
+
</div>
|
|
336
|
+
</div>
|
|
337
|
+
|
|
338
|
+
<div id="errorMessage"></div>
|
|
339
|
+
|
|
340
|
+
<div class="summary">
|
|
341
|
+
<h2>Summary</h2>
|
|
342
|
+
<div class="summary-grid">
|
|
343
|
+
<div class="summary-item">
|
|
344
|
+
<div class="count" id="functionsCount">0</div>
|
|
345
|
+
<div class="label">Unreachable Functions</div>
|
|
346
|
+
</div>
|
|
347
|
+
<div class="summary-item">
|
|
348
|
+
<div class="count" id="importsCount">0</div>
|
|
349
|
+
<div class="label">Unused Imports</div>
|
|
350
|
+
</div>
|
|
351
|
+
<div class="summary-item">
|
|
352
|
+
<div class="count" id="parametersCount">0</div>
|
|
353
|
+
<div class="label">Unused Parameters</div>
|
|
354
|
+
</div>
|
|
355
|
+
<div class="summary-item">
|
|
356
|
+
<div class="count" id="variablesCount">0</div>
|
|
357
|
+
<div class="label">Unused Variables</div>
|
|
358
|
+
</div>
|
|
359
|
+
<div class="summary-item">
|
|
360
|
+
<div class="count" id="classesCount">0</div>
|
|
361
|
+
<div class="label">Unused Classes</div>
|
|
362
|
+
</div>
|
|
363
|
+
</div>
|
|
364
|
+
</div>
|
|
365
|
+
|
|
366
|
+
<div class="results">
|
|
367
|
+
<h2>Dead Code Items</h2>
|
|
368
|
+
<div class="dead-code-list" id="deadCodeList">
|
|
369
|
+
<div class="no-results">
|
|
370
|
+
<p>Enter a project path and click "Analyze Project" to scan for dead code.</p>
|
|
371
|
+
</div>
|
|
372
|
+
</div>
|
|
373
|
+
</div>
|
|
374
|
+
</div>
|
|
375
|
+
|
|
376
|
+
<script>
|
|
377
|
+
let analysisData = null;
|
|
378
|
+
let confidenceThreshold = 60;
|
|
379
|
+
|
|
380
|
+
const slider = document.getElementById('confidenceSlider');
|
|
381
|
+
const confidenceValue = document.getElementById('confidenceValue');
|
|
382
|
+
const analyzeBtn = document.getElementById('analyzeBtn');
|
|
383
|
+
const folderPath = document.getElementById('folderPath');
|
|
384
|
+
const errorMessage = document.getElementById('errorMessage');
|
|
385
|
+
|
|
386
|
+
slider.addEventListener('input', (e) => {
|
|
387
|
+
confidenceThreshold = parseInt(e.target.value);
|
|
388
|
+
confidenceValue.textContent = confidenceThreshold;
|
|
389
|
+
if (analysisData) {
|
|
390
|
+
updateDisplay();
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
analyzeBtn.addEventListener('click', analyzeProject);
|
|
395
|
+
|
|
396
|
+
function showError(message) {
|
|
397
|
+
errorMessage.innerHTML = `<div class="error">${message}</div>`;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function clearError() {
|
|
401
|
+
errorMessage.innerHTML = '';
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
async function analyzeProject() {
|
|
405
|
+
const path = folderPath.value.trim();
|
|
406
|
+
if (!path) {
|
|
407
|
+
showError('Please enter a project path');
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
clearError();
|
|
412
|
+
analyzeBtn.textContent = 'Analyzing...';
|
|
413
|
+
analyzeBtn.disabled = true;
|
|
414
|
+
|
|
415
|
+
document.getElementById('deadCodeList').innerHTML = '<div class="loading">Analyzing project...</div>';
|
|
416
|
+
|
|
417
|
+
try {
|
|
418
|
+
const response = await fetch('/api/analyze', {
|
|
419
|
+
method: 'POST',
|
|
420
|
+
headers: {
|
|
421
|
+
'Content-Type': 'application/json',
|
|
422
|
+
},
|
|
423
|
+
body: JSON.stringify({
|
|
424
|
+
path: path,
|
|
425
|
+
confidence: confidenceThreshold
|
|
426
|
+
})
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
if (!response.ok) {
|
|
430
|
+
const errorData = await response.json();
|
|
431
|
+
throw new Error(errorData.error || `Analysis failed: ${response.statusText}`);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const result = await response.json();
|
|
435
|
+
analysisData = result;
|
|
436
|
+
updateDisplay();
|
|
437
|
+
|
|
438
|
+
} catch (error) {
|
|
439
|
+
showError(`Error: ${error.message}`);
|
|
440
|
+
document.getElementById('deadCodeList').innerHTML = '<div class="no-results"><p>Analysis failed. Check the error message above.</p></div>';
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
analyzeBtn.textContent = 'Analyze Project';
|
|
444
|
+
analyzeBtn.disabled = false;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function updateDisplay() {
|
|
448
|
+
if (!analysisData) return;
|
|
449
|
+
|
|
450
|
+
const filteredData = getFilteredData();
|
|
451
|
+
updateSummary(filteredData);
|
|
452
|
+
updateDeadCodeList(filteredData);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function getFilteredData() {
|
|
456
|
+
const data = {
|
|
457
|
+
functions: analysisData.unused_functions || [],
|
|
458
|
+
imports: analysisData.unused_imports || [],
|
|
459
|
+
parameters: analysisData.unused_parameters || [],
|
|
460
|
+
variables: analysisData.unused_variables || [],
|
|
461
|
+
classes: analysisData.unused_classes || []
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
// Filter by confidence threshold
|
|
465
|
+
Object.keys(data).forEach(key => {
|
|
466
|
+
data[key] = data[key].filter(item => item.confidence >= confidenceThreshold);
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
return data;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function updateSummary(data) {
|
|
473
|
+
document.getElementById('functionsCount').textContent = data.functions.length;
|
|
474
|
+
document.getElementById('importsCount').textContent = data.imports.length;
|
|
475
|
+
document.getElementById('parametersCount').textContent = data.parameters.length;
|
|
476
|
+
document.getElementById('variablesCount').textContent = data.variables.length;
|
|
477
|
+
document.getElementById('classesCount').textContent = data.classes.length;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function updateDeadCodeList(data) {
|
|
481
|
+
const listElement = document.getElementById('deadCodeList');
|
|
482
|
+
const allItems = [];
|
|
483
|
+
|
|
484
|
+
// Combine all items with their categories
|
|
485
|
+
Object.keys(data).forEach(category => {
|
|
486
|
+
data[category].forEach(item => {
|
|
487
|
+
allItems.push({
|
|
488
|
+
...item,
|
|
489
|
+
category: category.slice(0, -1) // Remove 's' from end
|
|
490
|
+
});
|
|
491
|
+
});
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
if (allItems.length === 0) {
|
|
495
|
+
listElement.innerHTML = `
|
|
496
|
+
<div class="no-results">
|
|
497
|
+
<p>No dead code found at confidence level ${confidenceThreshold}%</p>
|
|
498
|
+
</div>
|
|
499
|
+
`;
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Sort by confidence (highest first)
|
|
504
|
+
allItems.sort((a, b) => b.confidence - a.confidence);
|
|
505
|
+
|
|
506
|
+
listElement.innerHTML = allItems.map(item => `
|
|
507
|
+
<div class="dead-code-item">
|
|
508
|
+
<div class="item-details">
|
|
509
|
+
<div class="item-name">${item.name}</div>
|
|
510
|
+
<div class="item-location">${item.file}:${item.line}</div>
|
|
511
|
+
</div>
|
|
512
|
+
<div class="item-meta">
|
|
513
|
+
<span class="item-type">${item.category}</span>
|
|
514
|
+
<span class="item-confidence">${item.confidence}%</span>
|
|
515
|
+
</div>
|
|
516
|
+
</div>
|
|
517
|
+
`).join('');
|
|
518
|
+
}
|
|
519
|
+
</script>
|
|
520
|
+
</body>
|
|
521
|
+
</html>"""
|
|
522
|
+
|
|
523
|
+
@app.route('/api/analyze', methods=['POST'])
|
|
524
|
+
def analyze_project():
|
|
525
|
+
"""Analyze a project using skylos"""
|
|
526
|
+
try:
|
|
527
|
+
data = request.json
|
|
528
|
+
path = data.get('path')
|
|
529
|
+
confidence = data.get('confidence', 60)
|
|
530
|
+
|
|
531
|
+
if not path:
|
|
532
|
+
return jsonify({'error': 'Path is required'}), 400
|
|
533
|
+
|
|
534
|
+
if not os.path.exists(path):
|
|
535
|
+
return jsonify({'error': f'Path does not exist: {path}'}), 400
|
|
536
|
+
|
|
537
|
+
# Call your actual skylos analyzer
|
|
538
|
+
result_json = skylos.analyze(path, conf=confidence)
|
|
539
|
+
result = json.loads(result_json)
|
|
540
|
+
|
|
541
|
+
return jsonify(result)
|
|
542
|
+
|
|
543
|
+
except Exception as e:
|
|
544
|
+
return jsonify({'error': str(e)}), 500
|
|
545
|
+
|
|
546
|
+
def start_server():
|
|
547
|
+
"""Start the web server"""
|
|
548
|
+
def open_browser():
|
|
549
|
+
webbrowser.open('http://localhost:5090')
|
|
550
|
+
|
|
551
|
+
print(" Starting Skylos Web Interface...")
|
|
552
|
+
print("Opening browser at: http://localhost:5090")
|
|
553
|
+
|
|
554
|
+
# Open browser after a short delay
|
|
555
|
+
Timer(1.5, open_browser).start()
|
|
556
|
+
|
|
557
|
+
app.run(debug=False, host='0.0.0.0', port=5090, use_reloader=False)
|
|
558
|
+
|
|
559
|
+
if __name__ == '__main__':
|
|
560
|
+
start_server()
|
skylos/test_aware.py
CHANGED