ttnn-visualizer 0.70.0__py3-none-any.whl → 0.71.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.
- ttnn_visualizer/app.py +32 -1
- ttnn_visualizer/csv_queries.py +62 -35
- ttnn_visualizer/settings.py +9 -7
- ttnn_visualizer/sftp_operations.py +2 -3
- ttnn_visualizer/static/assets/{allPaths-DrpaDRaJ.js → allPaths-D6qA1aj4.js} +1 -1
- ttnn_visualizer/static/assets/allPathsLoader-t8G4bNwo.js +2 -0
- ttnn_visualizer/static/assets/{index-SMzJpwbG.js → index-8RVye9cY.js} +194 -194
- ttnn_visualizer/static/assets/{splitPathsBySizeLoader-Cg4d_fbJ.js → splitPathsBySizeLoader--w3Ey8_r.js} +1 -1
- ttnn_visualizer/static/index.html +1 -1
- ttnn_visualizer/tests/test_utils.py +98 -6
- ttnn_visualizer/utils.py +257 -3
- ttnn_visualizer/views.py +2 -2
- {ttnn_visualizer-0.70.0.dist-info → ttnn_visualizer-0.71.0.dist-info}/METADATA +2 -2
- {ttnn_visualizer-0.70.0.dist-info → ttnn_visualizer-0.71.0.dist-info}/RECORD +19 -19
- {ttnn_visualizer-0.70.0.dist-info → ttnn_visualizer-0.71.0.dist-info}/licenses/LICENSE +2 -0
- ttnn_visualizer/static/assets/allPathsLoader-C78guN8s.js +0 -2
- {ttnn_visualizer-0.70.0.dist-info → ttnn_visualizer-0.71.0.dist-info}/WHEEL +0 -0
- {ttnn_visualizer-0.70.0.dist-info → ttnn_visualizer-0.71.0.dist-info}/entry_points.txt +0 -0
- {ttnn_visualizer-0.70.0.dist-info → ttnn_visualizer-0.71.0.dist-info}/licenses/LICENSE_understanding.txt +0 -0
- {ttnn_visualizer-0.70.0.dist-info → ttnn_visualizer-0.71.0.dist-info}/top_level.txt +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{p as r,I as s,_ as a}from"./index-
|
|
1
|
+
import{p as r,I as s,_ as a}from"./index-8RVye9cY.js";const n=async(o,_)=>{const i=r(o);let t;return _===s.STANDARD?t=await a(()=>import("./index-BmDjQHI0.js").then(e=>e.I),[]):t=await a(()=>import("./index-CzNKtOwn.js").then(e=>e.I),[]),t[i]};export{n as splitPathsBySizeLoader};
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
/* SERVER_CONFIG */
|
|
35
35
|
</script>
|
|
36
36
|
|
|
37
|
-
<script type="module" crossorigin src="/static/assets/index-
|
|
37
|
+
<script type="module" crossorigin src="/static/assets/index-8RVye9cY.js"></script>
|
|
38
38
|
<link rel="stylesheet" crossorigin href="/static/assets/index-BVzPYDVR.css">
|
|
39
39
|
</head>
|
|
40
40
|
<body>
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-FileCopyrightText: © 2025 Tenstorrent AI ULC
|
|
4
4
|
|
|
5
|
+
from pathlib import Path
|
|
5
6
|
from unittest.mock import mock_open, patch
|
|
6
7
|
|
|
7
8
|
from ttnn_visualizer.utils import (
|
|
8
9
|
find_gunicorn_path,
|
|
9
10
|
get_app_data_directory,
|
|
11
|
+
get_report_data_directory,
|
|
10
12
|
is_running_in_container,
|
|
11
13
|
)
|
|
12
14
|
|
|
@@ -311,24 +313,34 @@ def test_get_app_data_directory_with_tt_metal_home():
|
|
|
311
313
|
assert result == "/path/to/tt-metal/generated/ttnn-visualizer"
|
|
312
314
|
|
|
313
315
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
+
@patch("os.getenv")
|
|
317
|
+
@patch("ttnn_visualizer.utils.is_running_in_container", return_value=False)
|
|
318
|
+
@patch("pathlib.Path.home", return_value=Path("/home/testuser"))
|
|
319
|
+
def test_get_app_data_directory_with_none(mock_home, mock_container, mock_getenv):
|
|
320
|
+
"""Test that get_app_data_directory returns ~/.ttnn-visualizer/app when tt_metal_home is None."""
|
|
321
|
+
mock_getenv.return_value = None # No APP_DATA_DIRECTORY env var
|
|
316
322
|
tt_metal_home = None
|
|
317
323
|
application_dir = "/default/app/dir"
|
|
318
324
|
|
|
319
325
|
result = get_app_data_directory(tt_metal_home, application_dir)
|
|
320
326
|
|
|
321
|
-
assert result == "/
|
|
327
|
+
assert result == "/home/testuser/.ttnn-visualizer/app"
|
|
322
328
|
|
|
323
329
|
|
|
324
|
-
|
|
325
|
-
|
|
330
|
+
@patch("os.getenv")
|
|
331
|
+
@patch("ttnn_visualizer.utils.is_running_in_container", return_value=False)
|
|
332
|
+
@patch("pathlib.Path.home", return_value=Path("/home/testuser"))
|
|
333
|
+
def test_get_app_data_directory_with_empty_string(
|
|
334
|
+
mock_home, mock_container, mock_getenv
|
|
335
|
+
):
|
|
336
|
+
"""Test that get_app_data_directory returns ~/.ttnn-visualizer/app when tt_metal_home is empty."""
|
|
337
|
+
mock_getenv.return_value = None # No APP_DATA_DIRECTORY env var
|
|
326
338
|
tt_metal_home = ""
|
|
327
339
|
application_dir = "/default/app/dir"
|
|
328
340
|
|
|
329
341
|
result = get_app_data_directory(tt_metal_home, application_dir)
|
|
330
342
|
|
|
331
|
-
assert result == "/
|
|
343
|
+
assert result == "/home/testuser/.ttnn-visualizer/app"
|
|
332
344
|
|
|
333
345
|
|
|
334
346
|
def test_get_app_data_directory_with_special_characters():
|
|
@@ -360,3 +372,83 @@ def test_get_app_data_directory_with_trailing_slash():
|
|
|
360
372
|
|
|
361
373
|
# Path.join handles trailing slashes correctly
|
|
362
374
|
assert result == "/path/to/tt-metal/generated/ttnn-visualizer"
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
@patch("os.getenv")
|
|
378
|
+
@patch("ttnn_visualizer.utils.is_running_in_container", return_value=False)
|
|
379
|
+
@patch("pathlib.Path.home", return_value=Path("/home/testuser"))
|
|
380
|
+
def test_get_app_data_directory_with_env_var(mock_home, mock_container, mock_getenv):
|
|
381
|
+
"""Test that get_app_data_directory respects APP_DATA_DIRECTORY environment variable."""
|
|
382
|
+
mock_getenv.side_effect = lambda key, default=None: (
|
|
383
|
+
"/custom/app/data" if key == "APP_DATA_DIRECTORY" else None
|
|
384
|
+
)
|
|
385
|
+
tt_metal_home = None
|
|
386
|
+
application_dir = "/default/app/dir"
|
|
387
|
+
|
|
388
|
+
result = get_app_data_directory(tt_metal_home, application_dir)
|
|
389
|
+
|
|
390
|
+
assert result == "/custom/app/data"
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
@patch("os.getenv")
|
|
394
|
+
@patch("ttnn_visualizer.utils.is_running_in_container", return_value=True)
|
|
395
|
+
@patch("os.geteuid", return_value=0)
|
|
396
|
+
def test_get_app_data_directory_in_container_as_root(
|
|
397
|
+
mock_geteuid, mock_container, mock_getenv
|
|
398
|
+
):
|
|
399
|
+
"""Test that get_app_data_directory returns /var/lib/ttnn-visualizer/app when running as root in container."""
|
|
400
|
+
mock_getenv.return_value = None # No APP_DATA_DIRECTORY env var
|
|
401
|
+
tt_metal_home = None
|
|
402
|
+
application_dir = "/default/app/dir"
|
|
403
|
+
|
|
404
|
+
result = get_app_data_directory(tt_metal_home, application_dir)
|
|
405
|
+
|
|
406
|
+
assert result == "/var/lib/ttnn-visualizer/app"
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
@patch("os.getenv")
|
|
410
|
+
@patch("ttnn_visualizer.utils.is_running_in_container", return_value=True)
|
|
411
|
+
@patch("os.geteuid", return_value=1000)
|
|
412
|
+
@patch("pathlib.Path.home", return_value=Path("/home/testuser"))
|
|
413
|
+
def test_get_app_data_directory_in_container_as_non_root(
|
|
414
|
+
mock_home, mock_geteuid, mock_container, mock_getenv
|
|
415
|
+
):
|
|
416
|
+
"""Test that get_app_data_directory returns ~/.ttnn-visualizer/app when running as non-root in container."""
|
|
417
|
+
mock_getenv.return_value = None # No APP_DATA_DIRECTORY env var
|
|
418
|
+
tt_metal_home = None
|
|
419
|
+
application_dir = "/default/app/dir"
|
|
420
|
+
|
|
421
|
+
result = get_app_data_directory(tt_metal_home, application_dir)
|
|
422
|
+
|
|
423
|
+
assert result == "/home/testuser/.ttnn-visualizer/app"
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
# Tests for get_report_data_directory()
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
@patch("os.getenv")
|
|
430
|
+
@patch("ttnn_visualizer.utils.is_running_in_container", return_value=False)
|
|
431
|
+
@patch("pathlib.Path.home", return_value=Path("/home/testuser"))
|
|
432
|
+
def test_get_report_data_directory_default(mock_home, mock_container, mock_getenv):
|
|
433
|
+
"""Test that get_report_data_directory returns ~/.ttnn-visualizer/reports by default."""
|
|
434
|
+
mock_getenv.return_value = None # No REPORT_DATA_DIRECTORY env var
|
|
435
|
+
tt_metal_home = None
|
|
436
|
+
application_dir = "/default/app/dir"
|
|
437
|
+
|
|
438
|
+
result = get_report_data_directory(tt_metal_home, application_dir)
|
|
439
|
+
|
|
440
|
+
assert result == "/home/testuser/.ttnn-visualizer/reports"
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
@patch("os.getenv")
|
|
444
|
+
def test_get_report_data_directory_with_env_var(mock_getenv):
|
|
445
|
+
"""Test that get_report_data_directory respects REPORT_DATA_DIRECTORY environment variable."""
|
|
446
|
+
mock_getenv.side_effect = lambda key, default=None: (
|
|
447
|
+
"/custom/reports" if key == "REPORT_DATA_DIRECTORY" else None
|
|
448
|
+
)
|
|
449
|
+
tt_metal_home = None
|
|
450
|
+
application_dir = "/default/app/dir"
|
|
451
|
+
|
|
452
|
+
result = get_report_data_directory(tt_metal_home, application_dir)
|
|
453
|
+
|
|
454
|
+
assert result == "/custom/reports"
|
ttnn_visualizer/utils.py
CHANGED
|
@@ -9,6 +9,7 @@ import logging
|
|
|
9
9
|
import os
|
|
10
10
|
import re
|
|
11
11
|
import shutil
|
|
12
|
+
import sqlite3
|
|
12
13
|
import sys
|
|
13
14
|
import time
|
|
14
15
|
from functools import wraps
|
|
@@ -23,18 +24,271 @@ LAST_SYNCED_FILE_NAME = ".last-synced"
|
|
|
23
24
|
|
|
24
25
|
def get_app_data_directory(tt_metal_home: Optional[str], application_dir: str) -> str:
|
|
25
26
|
"""
|
|
26
|
-
Calculate the APP_DATA_DIRECTORY
|
|
27
|
+
Calculate the APP_DATA_DIRECTORY with sensible defaults.
|
|
28
|
+
|
|
29
|
+
Priority:
|
|
30
|
+
1. TT_METAL_HOME (if set) -> {tt_metal_home}/generated/ttnn-visualizer
|
|
31
|
+
2. Environment variable APP_DATA_DIRECTORY (if set)
|
|
32
|
+
3. Container detection -> /var/lib/ttnn-visualizer/app (root) or ~/.ttnn-visualizer/app (non-root)
|
|
33
|
+
4. Regular user -> ~/.ttnn-visualizer/app
|
|
27
34
|
|
|
28
35
|
Args:
|
|
29
36
|
tt_metal_home: Path to TT-Metal home directory, or None
|
|
30
|
-
application_dir: Fallback application directory path
|
|
37
|
+
application_dir: Fallback application directory path (legacy, used for migration detection)
|
|
31
38
|
|
|
32
39
|
Returns:
|
|
33
40
|
Path to the app data directory
|
|
34
41
|
"""
|
|
42
|
+
# Priority 1: TT_METAL_HOME mode
|
|
35
43
|
if tt_metal_home and tt_metal_home.strip():
|
|
36
44
|
return str(Path(tt_metal_home).expanduser() / "generated" / "ttnn-visualizer")
|
|
37
|
-
|
|
45
|
+
|
|
46
|
+
# Priority 2: Explicit environment variable
|
|
47
|
+
if env_dir := os.getenv("APP_DATA_DIRECTORY"):
|
|
48
|
+
return env_dir
|
|
49
|
+
|
|
50
|
+
# Priority 3: Container detection
|
|
51
|
+
if is_running_in_container():
|
|
52
|
+
# If running as root in container, use /var/lib
|
|
53
|
+
try:
|
|
54
|
+
if os.geteuid() == 0:
|
|
55
|
+
return "/var/lib/ttnn-visualizer/app"
|
|
56
|
+
except AttributeError:
|
|
57
|
+
# Windows doesn't have geteuid(), assume non-root
|
|
58
|
+
pass
|
|
59
|
+
# Otherwise use home directory (even in container)
|
|
60
|
+
return str(Path.home() / ".ttnn-visualizer" / "app")
|
|
61
|
+
|
|
62
|
+
# Priority 4: Default for regular users
|
|
63
|
+
return str(Path.home() / ".ttnn-visualizer" / "app")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def get_report_data_directory(
|
|
67
|
+
tt_metal_home: Optional[str], application_dir: str
|
|
68
|
+
) -> str:
|
|
69
|
+
"""
|
|
70
|
+
Calculate the REPORT_DATA_DIRECTORY with sensible defaults.
|
|
71
|
+
|
|
72
|
+
Uses the same base directory as app data, but points to reports subdirectory.
|
|
73
|
+
Structure: {base}/reports (where base is ~/.ttnn-visualizer or /var/lib/ttnn-visualizer)
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
tt_metal_home: Path to TT-Metal home directory, or None
|
|
77
|
+
application_dir: Fallback application directory path (legacy, used for migration detection)
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Path to the report data directory
|
|
81
|
+
"""
|
|
82
|
+
# Priority 1: Explicit environment variable
|
|
83
|
+
if env_dir := os.getenv("REPORT_DATA_DIRECTORY"):
|
|
84
|
+
return env_dir
|
|
85
|
+
|
|
86
|
+
# Priority 2: Use same base as app data, but in reports subdirectory
|
|
87
|
+
app_data_dir = get_app_data_directory(tt_metal_home, application_dir)
|
|
88
|
+
base_dir = Path(app_data_dir).parent
|
|
89
|
+
return str(base_dir / "reports")
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def migrate_old_data_directory(
|
|
93
|
+
old_app_data_dir: str,
|
|
94
|
+
old_report_data_dir: str,
|
|
95
|
+
new_app_data_dir: str,
|
|
96
|
+
new_report_data_dir: str,
|
|
97
|
+
db_version: str,
|
|
98
|
+
) -> bool:
|
|
99
|
+
"""
|
|
100
|
+
Migrate data from old site-packages directory to new user directory.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
old_app_data_dir: Old app data directory (typically in site-packages)
|
|
104
|
+
old_report_data_dir: Old report data directory (typically in site-packages)
|
|
105
|
+
new_app_data_dir: New app data directory (typically ~/.ttnn-visualizer/app)
|
|
106
|
+
new_report_data_dir: New report data directory (typically ~/.ttnn-visualizer/reports)
|
|
107
|
+
db_version: Database version string (e.g., "0.29.0") to construct database filename
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
True if migration was performed, False otherwise
|
|
111
|
+
"""
|
|
112
|
+
old_app_path = Path(old_app_data_dir)
|
|
113
|
+
old_report_path = Path(old_report_data_dir)
|
|
114
|
+
new_app_path = Path(new_app_data_dir)
|
|
115
|
+
new_report_path = Path(new_report_data_dir)
|
|
116
|
+
|
|
117
|
+
# Construct the database filename
|
|
118
|
+
db_filename = f"ttnn_{db_version}.db"
|
|
119
|
+
old_db_path = old_app_path / db_filename
|
|
120
|
+
|
|
121
|
+
# Check if old directories exist and have data
|
|
122
|
+
old_app_has_data = old_db_path.exists()
|
|
123
|
+
old_report_has_data = old_report_path.exists() and any(old_report_path.iterdir())
|
|
124
|
+
|
|
125
|
+
if not old_app_has_data and not old_report_has_data:
|
|
126
|
+
return False
|
|
127
|
+
|
|
128
|
+
# Check if new directories already have data (don't overwrite)
|
|
129
|
+
new_db_path = new_app_path / db_filename
|
|
130
|
+
new_app_has_data = new_db_path.exists()
|
|
131
|
+
new_report_has_data = new_report_path.exists() and any(new_report_path.iterdir())
|
|
132
|
+
|
|
133
|
+
if new_app_has_data or new_report_has_data:
|
|
134
|
+
logger.info(
|
|
135
|
+
f"New data directories already exist with data, skipping migration. "
|
|
136
|
+
f"App: {new_app_path}, Reports: {new_report_path}"
|
|
137
|
+
)
|
|
138
|
+
return False
|
|
139
|
+
|
|
140
|
+
# Check if old directory is actually in site-packages (to avoid migrating from custom locations)
|
|
141
|
+
old_app_str = str(old_app_path)
|
|
142
|
+
if "site-packages" not in old_app_str and "dist-packages" not in old_app_str:
|
|
143
|
+
logger.info(
|
|
144
|
+
f"Old app data directory is not in site-packages, skipping migration: {old_app_path}"
|
|
145
|
+
)
|
|
146
|
+
return False
|
|
147
|
+
|
|
148
|
+
print("\n" + "=" * 70)
|
|
149
|
+
print("📦 DATA DIRECTORY MIGRATION")
|
|
150
|
+
print("=" * 70)
|
|
151
|
+
print(f"Detected old data in site-packages directory.")
|
|
152
|
+
print(f" Old app data: {old_app_path}")
|
|
153
|
+
print(f" Old reports: {old_report_path}")
|
|
154
|
+
print(f"\nNew location:")
|
|
155
|
+
print(f" New app data: {new_app_path}")
|
|
156
|
+
print(f" New reports: {new_report_path}")
|
|
157
|
+
print("\nWould you like to migrate the data? (y/n): ", end="", flush=True)
|
|
158
|
+
|
|
159
|
+
try:
|
|
160
|
+
response = input().strip().lower()
|
|
161
|
+
if response not in ("y", "yes"):
|
|
162
|
+
print("Migration cancelled by user.")
|
|
163
|
+
return False
|
|
164
|
+
except (EOFError, KeyboardInterrupt):
|
|
165
|
+
print("\nMigration cancelled.")
|
|
166
|
+
return False
|
|
167
|
+
|
|
168
|
+
# Create new directories
|
|
169
|
+
new_app_path.mkdir(parents=True, exist_ok=True)
|
|
170
|
+
new_report_path.mkdir(parents=True, exist_ok=True)
|
|
171
|
+
|
|
172
|
+
migrated = False
|
|
173
|
+
|
|
174
|
+
# Migrate app data (only the specific database file)
|
|
175
|
+
if old_app_has_data:
|
|
176
|
+
print(f"\nMigrating database file from {old_app_path} to {new_app_path}...")
|
|
177
|
+
try:
|
|
178
|
+
# Move the database file
|
|
179
|
+
shutil.move(str(old_db_path), str(new_db_path))
|
|
180
|
+
print(f" ✓ Moved {db_filename}")
|
|
181
|
+
migrated = True
|
|
182
|
+
except Exception as e:
|
|
183
|
+
logger.error(f"Error migrating database file: {e}")
|
|
184
|
+
print(f" ❌ Error: {e}")
|
|
185
|
+
|
|
186
|
+
# Migrate report data (all files and directories)
|
|
187
|
+
if old_report_has_data:
|
|
188
|
+
print(f"\nMigrating reports from {old_report_path} to {new_report_path}...")
|
|
189
|
+
try:
|
|
190
|
+
for item in old_report_path.iterdir():
|
|
191
|
+
dest = new_report_path / item.name
|
|
192
|
+
if item.is_file():
|
|
193
|
+
shutil.move(str(item), str(dest))
|
|
194
|
+
print(f" ✓ Moved {item.name}")
|
|
195
|
+
elif item.is_dir():
|
|
196
|
+
shutil.move(str(item), str(dest))
|
|
197
|
+
print(f" ✓ Moved directory {item.name}")
|
|
198
|
+
migrated = True
|
|
199
|
+
except Exception as e:
|
|
200
|
+
logger.error(f"Error migrating report data: {e}")
|
|
201
|
+
print(f" ❌ Error: {e}")
|
|
202
|
+
|
|
203
|
+
# Update paths in the database after migration
|
|
204
|
+
# Note: We use the old_report_path for matching even though files are moved,
|
|
205
|
+
# because the database still contains the old paths that need to be updated
|
|
206
|
+
if migrated and old_app_has_data:
|
|
207
|
+
print(f"\nUpdating paths in database...")
|
|
208
|
+
try:
|
|
209
|
+
_update_database_paths(new_db_path, old_report_path, new_report_path)
|
|
210
|
+
print(f" ✓ Updated paths in database")
|
|
211
|
+
except Exception as e:
|
|
212
|
+
logger.error(f"Error updating database paths: {e}")
|
|
213
|
+
print(f" ⚠️ Warning: Could not update paths in database: {e}")
|
|
214
|
+
print(f" You may need to manually update paths in the instances table.")
|
|
215
|
+
|
|
216
|
+
if migrated:
|
|
217
|
+
print("\n✅ Migration completed successfully!")
|
|
218
|
+
print(f" Data has been moved from: {old_app_path}")
|
|
219
|
+
else:
|
|
220
|
+
print("\n⚠️ No data was migrated.")
|
|
221
|
+
|
|
222
|
+
print("=" * 70 + "\n")
|
|
223
|
+
|
|
224
|
+
return migrated
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def _update_database_paths(
|
|
228
|
+
db_path: Path, old_report_data_dir: Path, new_report_data_dir: Path
|
|
229
|
+
) -> None:
|
|
230
|
+
"""
|
|
231
|
+
Update absolute paths in the instances table after migration.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
db_path: Path to the SQLite database file
|
|
235
|
+
old_report_data_dir: Old report data directory path
|
|
236
|
+
new_report_data_dir: New report data directory path
|
|
237
|
+
"""
|
|
238
|
+
# Normalize paths to handle symlinks and ensure consistent format
|
|
239
|
+
old_report_data_dir = old_report_data_dir.resolve()
|
|
240
|
+
new_report_data_dir = new_report_data_dir.resolve()
|
|
241
|
+
old_report_str = str(old_report_data_dir)
|
|
242
|
+
new_report_str = str(new_report_data_dir)
|
|
243
|
+
|
|
244
|
+
try:
|
|
245
|
+
conn = sqlite3.connect(str(db_path))
|
|
246
|
+
cursor = conn.cursor()
|
|
247
|
+
|
|
248
|
+
# Update profiler_path
|
|
249
|
+
cursor.execute(
|
|
250
|
+
"""
|
|
251
|
+
UPDATE instances
|
|
252
|
+
SET profiler_path = REPLACE(profiler_path, ?, ?)
|
|
253
|
+
WHERE profiler_path LIKE ? || '%'
|
|
254
|
+
""",
|
|
255
|
+
(old_report_str, new_report_str, old_report_str),
|
|
256
|
+
)
|
|
257
|
+
profiler_updated = cursor.rowcount
|
|
258
|
+
|
|
259
|
+
# Update performance_path
|
|
260
|
+
cursor.execute(
|
|
261
|
+
"""
|
|
262
|
+
UPDATE instances
|
|
263
|
+
SET performance_path = REPLACE(performance_path, ?, ?)
|
|
264
|
+
WHERE performance_path LIKE ? || '%'
|
|
265
|
+
""",
|
|
266
|
+
(old_report_str, new_report_str, old_report_str),
|
|
267
|
+
)
|
|
268
|
+
performance_updated = cursor.rowcount
|
|
269
|
+
|
|
270
|
+
# Update npe_path
|
|
271
|
+
cursor.execute(
|
|
272
|
+
"""
|
|
273
|
+
UPDATE instances
|
|
274
|
+
SET npe_path = REPLACE(npe_path, ?, ?)
|
|
275
|
+
WHERE npe_path LIKE ? || '%'
|
|
276
|
+
""",
|
|
277
|
+
(old_report_str, new_report_str, old_report_str),
|
|
278
|
+
)
|
|
279
|
+
npe_updated = cursor.rowcount
|
|
280
|
+
|
|
281
|
+
conn.commit()
|
|
282
|
+
conn.close()
|
|
283
|
+
|
|
284
|
+
if profiler_updated > 0 or performance_updated > 0 or npe_updated > 0:
|
|
285
|
+
logger.info(
|
|
286
|
+
f"Updated database paths: {profiler_updated} profiler_path, "
|
|
287
|
+
f"{performance_updated} performance_path, {npe_updated} npe_path"
|
|
288
|
+
)
|
|
289
|
+
except sqlite3.Error as e:
|
|
290
|
+
logger.error(f"SQLite error updating paths: {e}")
|
|
291
|
+
raise
|
|
38
292
|
|
|
39
293
|
|
|
40
294
|
def find_gunicorn_path() -> tuple[str, Optional[str]]:
|
ttnn_visualizer/views.py
CHANGED
|
@@ -732,10 +732,10 @@ def get_performance_results_report(instance: Instance):
|
|
|
732
732
|
start_signpost = request.args.get("start_signpost", None)
|
|
733
733
|
end_signpost = request.args.get("end_signpost", None)
|
|
734
734
|
print_signposts = str_to_bool(request.args.get("print_signposts", "true"))
|
|
735
|
-
stack_by_in0 = str_to_bool(request.args.get("stack_by_in0", "true"))
|
|
736
735
|
hide_host_ops = str_to_bool(request.args.get("hide_host_ops", "true"))
|
|
737
736
|
merge_devices = str_to_bool(request.args.get("merge_devices", "true"))
|
|
738
737
|
tracing_mode = str_to_bool(request.args.get("tracing_mode", "false"))
|
|
738
|
+
group_by = request.args.get("group_by", None)
|
|
739
739
|
|
|
740
740
|
if name and not current_app.config["SERVER_MODE"]:
|
|
741
741
|
performance_path = Path(instance.performance_path).parent / name
|
|
@@ -745,13 +745,13 @@ def get_performance_results_report(instance: Instance):
|
|
|
745
745
|
try:
|
|
746
746
|
report = OpsPerformanceReportQueries.generate_report(
|
|
747
747
|
instance,
|
|
748
|
-
stack_by_in0=stack_by_in0,
|
|
749
748
|
start_signpost=start_signpost,
|
|
750
749
|
print_signposts=print_signposts,
|
|
751
750
|
end_signpost=end_signpost,
|
|
752
751
|
hide_host_ops=hide_host_ops,
|
|
753
752
|
merge_devices=merge_devices,
|
|
754
753
|
tracing_mode=tracing_mode,
|
|
754
|
+
group_by=group_by,
|
|
755
755
|
)
|
|
756
756
|
except DataFormatError:
|
|
757
757
|
return Response(status=HTTPStatus.UNPROCESSABLE_ENTITY)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ttnn_visualizer
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.71.0
|
|
4
4
|
Summary: TT-NN Visualizer
|
|
5
5
|
Classifier: Programming Language :: Python :: 3
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -23,7 +23,7 @@ Requires-Dist: pydantic_core==2.27.1
|
|
|
23
23
|
Requires-Dist: pydantic==2.10.3
|
|
24
24
|
Requires-Dist: python-dotenv==1.0.1
|
|
25
25
|
Requires-Dist: PyYAML==6.0.2
|
|
26
|
-
Requires-Dist: tt-perf-report==1.1
|
|
26
|
+
Requires-Dist: tt-perf-report==1.2.1
|
|
27
27
|
Requires-Dist: uvicorn==0.30.1
|
|
28
28
|
Requires-Dist: zstd==1.5.7.0
|
|
29
29
|
Provides-Extra: dev
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
ttnn_visualizer/__init__.py,sha256=FCQeTWnXsf-Wx-fay53-lQsm0y5-GcPMUmzhE5upDx0,93
|
|
2
|
-
ttnn_visualizer/app.py,sha256=
|
|
3
|
-
ttnn_visualizer/csv_queries.py,sha256=
|
|
2
|
+
ttnn_visualizer/app.py,sha256=fiOg_aUMLPGZu_FjUemgpwJYzz6uE50lEvOcy8cuBp4,14631
|
|
3
|
+
ttnn_visualizer/csv_queries.py,sha256=Q3lLhcZ8FWelTEPHg7j9qaakeeFqltHLGEW8nOVwDpw,21897
|
|
4
4
|
ttnn_visualizer/decorators.py,sha256=YY_5zQdD9VOuBC5iP1Z9CEMjYz3ofD1Lc3ZrBvzQx8U,5779
|
|
5
5
|
ttnn_visualizer/enums.py,sha256=SEIqp1tlc_zw2vQ8nHH9YTaV0m3Cb8fjn_goqz5wurE,203
|
|
6
6
|
ttnn_visualizer/exceptions.py,sha256=KVZzb7YaWbq51DNMKPBcJHwG74RMYj_29WTSYOlXXeU,2096
|
|
@@ -11,21 +11,21 @@ ttnn_visualizer/models.py,sha256=6z0WwKWwaOhYMgHEIM5NHxiybDoipL3vJD1uRgZPuSI,862
|
|
|
11
11
|
ttnn_visualizer/pytest_plugin.py,sha256=bEG0cbqH0HUuZT5Ox9tFoexFNTyimBBPpI_jp75b54c,2629
|
|
12
12
|
ttnn_visualizer/queries.py,sha256=gfI8Jzlp7VHCh8VDSqgYqbhlf9eaj2QvwkXovNCjqXg,13620
|
|
13
13
|
ttnn_visualizer/serializers.py,sha256=mKxcDu9g4gAxHB6wP_1l5VJvIBmnYDIJTikiaMYXupg,9374
|
|
14
|
-
ttnn_visualizer/settings.py,sha256=
|
|
15
|
-
ttnn_visualizer/sftp_operations.py,sha256=
|
|
14
|
+
ttnn_visualizer/settings.py,sha256=4R9LVsxs9XRtJx6f7oW84jPeq4ffuDZkN2QEVE8Ie8Q,5216
|
|
15
|
+
ttnn_visualizer/sftp_operations.py,sha256=l5MEorNJ93e9X_Nf7fgLb3cSftuErE3PKzAki2T5Hpc,31585
|
|
16
16
|
ttnn_visualizer/sockets.py,sha256=_Hdne33r4FrB2tg58Vw87FWLbgQ_ikICVp4o1Mkv2mo,4789
|
|
17
17
|
ttnn_visualizer/ssh_client.py,sha256=x-BUUnsaKGReuOrSpHdcIaoH6RdGiQQYWx2_pOkGzJ0,13410
|
|
18
|
-
ttnn_visualizer/utils.py,sha256=
|
|
19
|
-
ttnn_visualizer/views.py,sha256=
|
|
20
|
-
ttnn_visualizer/static/index.html,sha256=
|
|
21
|
-
ttnn_visualizer/static/assets/allPaths-
|
|
22
|
-
ttnn_visualizer/static/assets/allPathsLoader-
|
|
18
|
+
ttnn_visualizer/utils.py,sha256=CzFX4AuVmHaAxq6ZklUk3PMWPliNb4-seAtRuXiDthg,27995
|
|
19
|
+
ttnn_visualizer/views.py,sha256=oD31TaN-g5Fb7G7oDFyRtuJYBUON_HGjGxI-EnQtF4Q,52477
|
|
20
|
+
ttnn_visualizer/static/index.html,sha256=QxpENVT5XwOnFv_Jh-AgcO3rBZRrI4rwG7zz3u738FM,1135
|
|
21
|
+
ttnn_visualizer/static/assets/allPaths-D6qA1aj4.js,sha256=BnjOCm8ifqgwLBAmRP5cO-lpMnZfAySNyoZoooU7vIA,255
|
|
22
|
+
ttnn_visualizer/static/assets/allPathsLoader-t8G4bNwo.js,sha256=j-q8s8ju02Aqy_3WaBo3fNtPHRw6tadfqH4aAdP-U7k,477
|
|
23
|
+
ttnn_visualizer/static/assets/index-8RVye9cY.js,sha256=-u_M4wiPslSSnTuq2OMyf2X_czVdzr1wUnTScyE6P_E,7982508
|
|
23
24
|
ttnn_visualizer/static/assets/index-BVzPYDVR.css,sha256=_fSlNYmeC54u6mXYoyiQDIXeRD9ajwaKIWE2M7e1uJk,618970
|
|
24
25
|
ttnn_visualizer/static/assets/index-BmDjQHI0.js,sha256=Np8PB0IkYR44ybu3HDpLI7b6XWw2sZQL-MIbQxV7CcA,294299
|
|
25
26
|
ttnn_visualizer/static/assets/index-CzNKtOwn.js,sha256=i4B-DZkbAK68FWdRZAGppuLcytv1ETOLu6m6s_0a7r4,303575
|
|
26
|
-
ttnn_visualizer/static/assets/index-SMzJpwbG.js,sha256=Rov-6MiS7qA_iMBXsUZIyCl58Zyx7_ofkHlXqm2V9WI,7980674
|
|
27
27
|
ttnn_visualizer/static/assets/site-BTBrvHC5.webmanifest,sha256=Uy_XmnGuYFVf-OZuma2NvgEPdrCrevb3HZvaxSIHoA0,456
|
|
28
|
-
ttnn_visualizer/static/assets/splitPathsBySizeLoader
|
|
28
|
+
ttnn_visualizer/static/assets/splitPathsBySizeLoader--w3Ey8_r.js,sha256=KAjd3n5fEUXoGPOA7V5JrfsPWnatp8tyl6xZ9LgqpBk,281
|
|
29
29
|
ttnn_visualizer/static/favicon/android-chrome-192x192.png,sha256=BZWA09Zxaa3fXbaeS6nhWo2e-DUSjm9ElzNQ_xTB5XU,6220
|
|
30
30
|
ttnn_visualizer/static/favicon/android-chrome-512x512.png,sha256=HBiJSZyguB3o8fMJuqIGcpeBy_9JOdImme3wD02UYCw,62626
|
|
31
31
|
ttnn_visualizer/static/favicon/favicon-32x32.png,sha256=Zw201qUsczQv1UvoQvJf5smQ2ss10xaTeWxmQNYCGtY,480
|
|
@@ -34,11 +34,11 @@ ttnn_visualizer/static/sample-data/cluster-desc.yaml,sha256=LMxOmsRUXtVVU5ogzYkX
|
|
|
34
34
|
ttnn_visualizer/tests/__init__.py,sha256=FCQeTWnXsf-Wx-fay53-lQsm0y5-GcPMUmzhE5upDx0,93
|
|
35
35
|
ttnn_visualizer/tests/test_queries.py,sha256=3je_FKRgZLdoDTfIe6kENLFXWUeeYVgY3ZDVnvWgCJo,13754
|
|
36
36
|
ttnn_visualizer/tests/test_serializers.py,sha256=KLzkqQhDlqPTaJ5MUy-r7Nb2WT2hp5aTm_ceA0tlxIo,18911
|
|
37
|
-
ttnn_visualizer/tests/test_utils.py,sha256=
|
|
38
|
-
ttnn_visualizer-0.
|
|
39
|
-
ttnn_visualizer-0.
|
|
40
|
-
ttnn_visualizer-0.
|
|
41
|
-
ttnn_visualizer-0.
|
|
42
|
-
ttnn_visualizer-0.
|
|
43
|
-
ttnn_visualizer-0.
|
|
44
|
-
ttnn_visualizer-0.
|
|
37
|
+
ttnn_visualizer/tests/test_utils.py,sha256=bI2oMdir9BIy1RsIXTn80VTOrnleL5exOMjpDfhp6JY,14938
|
|
38
|
+
ttnn_visualizer-0.71.0.dist-info/licenses/LICENSE,sha256=DsbsWC-ymVM85l4HKV_ruheRbr37-FJ8KGxL0_cZdb0,20463
|
|
39
|
+
ttnn_visualizer-0.71.0.dist-info/licenses/LICENSE_understanding.txt,sha256=pymi-yb_RvYM9p2ZA4iSNsImcvhDBBxlGuJCY9dTq7M,233
|
|
40
|
+
ttnn_visualizer-0.71.0.dist-info/METADATA,sha256=iScWAvGleF5cr1BuoDS-sWLI-GoQK2joTw-dVJ8QE8A,8911
|
|
41
|
+
ttnn_visualizer-0.71.0.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
|
|
42
|
+
ttnn_visualizer-0.71.0.dist-info/entry_points.txt,sha256=QpuUpkmQ_mEHJTMqOBdU0MH2Z4WF_9iFsGACeyyAO1E,61
|
|
43
|
+
ttnn_visualizer-0.71.0.dist-info/top_level.txt,sha256=M1EGkvDOuIfbhDbcUdz2-TSdmCtDoQ2Uyag9k5JLDSY,16
|
|
44
|
+
ttnn_visualizer-0.71.0.dist-info/RECORD,,
|
|
@@ -87,6 +87,8 @@ The following separate and independent dependencies are utilized by this project
|
|
|
87
87
|
- @eslint/eslintrc - MIT - https://github.com/eslint/eslintrc/blob/main/LICENSE
|
|
88
88
|
- @eslint/js - MIT - https://github.com/eslint/eslint/blob/main/LICENSE
|
|
89
89
|
- @eslint/rewrite - Apache-2.0 - https://github.com/eslint/rewrite/blob/main/LICENSE
|
|
90
|
+
- @tanstack/react-query - MIT - https://github.com/TanStack/query/blob/main/LICENSE
|
|
91
|
+
- @tanstack/react-query-devtools - MIT - https://github.com/TanStack/query/blob/main/LICENSE
|
|
90
92
|
- @tanstack/react-virtual - MIT - https://github.com/TanStack/virtual/blob/main/LICENSE
|
|
91
93
|
- @testing-library/dom - MIT - https://github.com/testing-library/dom-testing-library/blob/main/LICENSE
|
|
92
94
|
- @testing-library/jest-dom - MIT - https://github.com/testing-library/jest-dom/blob/main/LICENSE
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/allPaths-DrpaDRaJ.js","assets/index-BmDjQHI0.js","assets/index-CzNKtOwn.js","assets/index-SMzJpwbG.js","assets/index-BVzPYDVR.css"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{_ as e}from"./index-SMzJpwbG.js";const s=async(t,a)=>{const{getIconPaths:o}=await e(async()=>{const{getIconPaths:r}=await import("./allPaths-DrpaDRaJ.js");return{getIconPaths:r}},__vite__mapDeps([0,1,2,3,4]));return o(t,a)};export{s as allPathsLoader};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|