ttnn-visualizer 0.46.0__py3-none-any.whl → 0.48.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.
Files changed (24) hide show
  1. ttnn_visualizer/app.py +36 -1
  2. ttnn_visualizer/csv_queries.py +2 -1
  3. ttnn_visualizer/file_uploads.py +1 -1
  4. ttnn_visualizer/models.py +1 -0
  5. ttnn_visualizer/queries.py +1 -1
  6. ttnn_visualizer/settings.py +1 -0
  7. ttnn_visualizer/sockets.py +31 -0
  8. ttnn_visualizer/static/assets/{allPaths-esBqnTg5.js → allPaths-DyhSRH--.js} +1 -1
  9. ttnn_visualizer/static/assets/allPathsLoader-DXd_rN1a.js +2 -0
  10. ttnn_visualizer/static/assets/{index-BuHal8Ii.css → index-CZ0Uonoz.css} +2 -2
  11. ttnn_visualizer/static/assets/{index-BANm1CMY.js → index-T8PVeTUn.js} +227 -227
  12. ttnn_visualizer/static/assets/{splitPathsBySizeLoader-DYuDhweD.js → splitPathsBySizeLoader-Gsi3qlIM.js} +1 -1
  13. ttnn_visualizer/static/index.html +2 -2
  14. ttnn_visualizer/tests/test_serializers.py +6 -0
  15. ttnn_visualizer/utils.py +190 -28
  16. ttnn_visualizer/views.py +90 -31
  17. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/METADATA +2 -1
  18. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/RECORD +23 -23
  19. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/licenses/LICENSE +95 -50
  20. ttnn_visualizer/static/assets/allPathsLoader-KPOKJ-lr.js +0 -2
  21. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/WHEEL +0 -0
  22. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/entry_points.txt +0 -0
  23. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/licenses/LICENSE_understanding.txt +0 -0
  24. {ttnn_visualizer-0.46.0.dist-info → ttnn_visualizer-0.48.0.dist-info}/top_level.txt +0 -0
@@ -1 +1 @@
1
- import{p as r,I as s,_ as a}from"./index-BANm1CMY.js";const n=async(o,_)=>{const i=r(o);let t;return _===s.STANDARD?t=await a(()=>import("./index-03c8d4Gh.js").then(e=>e.I),[]):t=await a(()=>import("./index-PKNBViIU.js").then(e=>e.I),[]),t[i]};export{n as splitPathsBySizeLoader};
1
+ import{p as r,I as s,_ as a}from"./index-T8PVeTUn.js";const n=async(o,_)=>{const i=r(o);let t;return _===s.STANDARD?t=await a(()=>import("./index-03c8d4Gh.js").then(e=>e.I),[]):t=await a(()=>import("./index-PKNBViIU.js").then(e=>e.I),[]),t[i]};export{n as splitPathsBySizeLoader};
@@ -34,8 +34,8 @@
34
34
  /* SERVER_CONFIG */
35
35
  </script>
36
36
 
37
- <script type="module" crossorigin src="/static/assets/index-BANm1CMY.js"></script>
38
- <link rel="stylesheet" crossorigin href="/static/assets/index-BuHal8Ii.css">
37
+ <script type="module" crossorigin src="/static/assets/index-T8PVeTUn.js"></script>
38
+ <link rel="stylesheet" crossorigin href="/static/assets/index-CZ0Uonoz.css">
39
39
  </head>
40
40
  <body>
41
41
 
@@ -161,12 +161,14 @@ class TestSerializers(unittest.TestCase):
161
161
  "device_id": 1,
162
162
  "address": 1000,
163
163
  "buffer_type": 0,
164
+ "buffer_layout": None,
164
165
  "size": 256,
165
166
  },
166
167
  {
167
168
  "device_id": 2,
168
169
  "address": 2000,
169
170
  "buffer_type": 1,
171
+ "buffer_layout": None,
170
172
  "size": 512,
171
173
  },
172
174
  ],
@@ -179,6 +181,7 @@ class TestSerializers(unittest.TestCase):
179
181
  "device_id": 3,
180
182
  "address": 3000,
181
183
  "buffer_type": 1,
184
+ "buffer_layout": None,
182
185
  "size": 1024,
183
186
  },
184
187
  ],
@@ -260,12 +263,14 @@ class TestSerializers(unittest.TestCase):
260
263
  "device_id": 1,
261
264
  "address": 1000,
262
265
  "buffer_type": 0,
266
+ "buffer_layout": None,
263
267
  "size": 256,
264
268
  },
265
269
  {
266
270
  "device_id": 2,
267
271
  "address": 2000,
268
272
  "buffer_type": 1,
273
+ "buffer_layout": None,
269
274
  "size": 512,
270
275
  },
271
276
  ],
@@ -389,6 +394,7 @@ class TestSerializers(unittest.TestCase):
389
394
  "buffers": [
390
395
  {
391
396
  "address": 1000,
397
+ "buffer_layout": None,
392
398
  "buffer_type": 0,
393
399
  "device_id": 1,
394
400
  "max_size_per_bank": 256,
ttnn_visualizer/utils.py CHANGED
@@ -18,6 +18,127 @@ logger = logging.getLogger(__name__)
18
18
  LAST_SYNCED_FILE_NAME = ".last-synced"
19
19
 
20
20
 
21
+ class PathResolver:
22
+ """Centralized path resolution for both TT-Metal and upload/sync modes."""
23
+
24
+ def __init__(self, current_app):
25
+ self.current_app = current_app
26
+ self.tt_metal_home = current_app.config.get("TT_METAL_HOME")
27
+ self.is_direct_report_mode = bool(self.tt_metal_home)
28
+
29
+ def get_base_report_path(self, report_type: str, remote_connection=None):
30
+ """
31
+ Get the base path for a report type (profiler/performance).
32
+
33
+ Args:
34
+ report_type: Either 'profiler' or 'performance'
35
+ remote_connection: Optional remote connection for upload/sync mode
36
+
37
+ Returns:
38
+ Path object to the base directory for this report type
39
+ """
40
+ if self.is_direct_report_mode:
41
+ tt_metal_base = Path(self.tt_metal_home) / "generated"
42
+ if report_type == "profiler":
43
+ return tt_metal_base / "ttnn" / "reports"
44
+ elif report_type == "performance":
45
+ return tt_metal_base / "profiler" / "reports"
46
+ else:
47
+ raise ValueError(f"Unknown report type: {report_type}")
48
+ else:
49
+ # Upload/sync mode - use existing logic
50
+ local_dir = Path(self.current_app.config["LOCAL_DATA_DIRECTORY"])
51
+ remote_dir = Path(self.current_app.config["REMOTE_DATA_DIRECTORY"])
52
+
53
+ if remote_connection:
54
+ base_dir = remote_dir / remote_connection.host
55
+ else:
56
+ base_dir = local_dir
57
+
58
+ if report_type == "profiler":
59
+ return base_dir / self.current_app.config["PROFILER_DIRECTORY_NAME"]
60
+ elif report_type == "performance":
61
+ return base_dir / self.current_app.config["PERFORMANCE_DIRECTORY_NAME"]
62
+ else:
63
+ raise ValueError(f"Unknown report type: {report_type}")
64
+
65
+ def get_profiler_path(self, profiler_name: str, remote_connection=None):
66
+ """Get the full path to a profiler report's db.sqlite file."""
67
+ if not profiler_name:
68
+ return ""
69
+
70
+ base_path = self.get_base_report_path("profiler", remote_connection)
71
+
72
+ if self.is_direct_report_mode and not base_path.exists():
73
+ logger.warning(f"TT-Metal profiler reports not found: {base_path}")
74
+ return ""
75
+
76
+ profiler_path = base_path / profiler_name
77
+ target_path = profiler_path / self.current_app.config["SQLITE_DB_PATH"]
78
+
79
+ return str(target_path)
80
+
81
+ def get_performance_path(self, performance_name: str, remote_connection=None):
82
+ """Get the full path to a performance report directory."""
83
+ base_path = self.get_base_report_path("performance", remote_connection)
84
+
85
+ if self.is_direct_report_mode and not base_path.exists():
86
+ logger.warning(f"TT-Metal performance reports not found: {base_path}")
87
+ return ""
88
+
89
+ performance_path = base_path / performance_name
90
+ return str(performance_path)
91
+
92
+ def get_mode_info(self):
93
+ """Get information about the current mode for debugging/display."""
94
+ if self.is_direct_report_mode:
95
+ return {
96
+ "mode": "tt_metal",
97
+ "tt_metal_home": self.tt_metal_home,
98
+ "profiler_base": str(
99
+ Path(self.tt_metal_home) / "generated" / "ttnn" / "reports"
100
+ ),
101
+ "performance_base": str(
102
+ Path(self.tt_metal_home) / "generated" / "profiler" / "reports"
103
+ ),
104
+ }
105
+ else:
106
+ return {
107
+ "mode": "upload_sync",
108
+ "local_dir": str(self.current_app.config["LOCAL_DATA_DIRECTORY"]),
109
+ "remote_dir": str(self.current_app.config["REMOTE_DATA_DIRECTORY"]),
110
+ }
111
+
112
+ def validate_tt_metal_setup(self):
113
+ """Validate that TT-Metal directories exist and are accessible."""
114
+ if not self.is_direct_report_mode:
115
+ return True, "Not in TT-Metal mode"
116
+
117
+ tt_metal_base = Path(self.tt_metal_home)
118
+ if not tt_metal_base.exists():
119
+ return False, f"TT_METAL_HOME directory does not exist: {tt_metal_base}"
120
+
121
+ generated_dir = tt_metal_base / "generated"
122
+ if not generated_dir.exists():
123
+ return False, f"TT-Metal generated directory not found: {generated_dir}"
124
+
125
+ profiler_base = self.get_base_report_path("profiler")
126
+ performance_base = self.get_base_report_path("performance")
127
+
128
+ messages = []
129
+ if not profiler_base.exists():
130
+ messages.append(f"Profiler reports directory not found: {profiler_base}")
131
+ if not performance_base.exists():
132
+ messages.append(
133
+ f"Performance reports directory not found: {performance_base}"
134
+ )
135
+
136
+ if messages:
137
+ return False, "; ".join(messages)
138
+
139
+ return True, "TT-Metal setup is valid"
140
+
141
+
21
142
  def str_to_bool(string_value):
22
143
  return string_value.lower() in ("yes", "true", "t", "1")
23
144
 
@@ -52,20 +173,10 @@ def get_performance_path(performance_name, current_app, remote_connection=None):
52
173
  :param current_app: Flask current application object.
53
174
  :param remote_connection: Remote connection model instance
54
175
 
55
- :return: Profiler path as a string.
176
+ :return: Performance path as a string.
56
177
  """
57
- local_dir = Path(current_app.config["LOCAL_DATA_DIRECTORY"])
58
- remote_dir = Path(current_app.config["REMOTE_DATA_DIRECTORY"])
59
-
60
- if remote_connection:
61
- base_dir = Path(remote_dir).joinpath(remote_connection.host)
62
- else:
63
- base_dir = local_dir
64
-
65
- profiler_dir = base_dir / current_app.config["PERFORMANCE_DIRECTORY_NAME"]
66
- performance_path = profiler_dir / performance_name
67
-
68
- return str(performance_path)
178
+ resolver = PathResolver(current_app)
179
+ return resolver.get_performance_path(performance_name, remote_connection)
69
180
 
70
181
 
71
182
  def get_profiler_path(profiler_name, current_app, remote_connection=None):
@@ -77,24 +188,75 @@ def get_profiler_path(profiler_name, current_app, remote_connection=None):
77
188
 
78
189
  :return: profiler_path as a string
79
190
  """
80
- database_file_name = current_app.config["SQLITE_DB_PATH"]
81
- local_dir = current_app.config["LOCAL_DATA_DIRECTORY"]
82
- remote_dir = current_app.config["REMOTE_DATA_DIRECTORY"]
191
+ resolver = PathResolver(current_app)
192
+ return resolver.get_profiler_path(profiler_name, remote_connection)
83
193
 
84
- if profiler_name:
85
- if remote_connection:
86
- base_dir = Path(remote_dir).joinpath(remote_connection.host)
87
- else:
88
- base_dir = local_dir
89
194
 
90
- profiler_path = (
91
- base_dir / current_app.config["PROFILER_DIRECTORY_NAME"] / profiler_name
92
- )
93
- target_path = profiler_path / database_file_name
195
+ def create_path_resolver(current_app):
196
+ """Create a PathResolver instance for the current app."""
197
+ return PathResolver(current_app)
94
198
 
95
- return str(target_path)
96
- else:
97
- return ""
199
+
200
+ def get_available_reports(current_app):
201
+ """
202
+ Get available reports in the current mode.
203
+
204
+ Returns a dict with 'profiler' and 'performance' keys containing lists of available reports.
205
+ This is a convenience function for views that need to discover available reports.
206
+ """
207
+ resolver = PathResolver(current_app)
208
+
209
+ reports = {"profiler": [], "performance": []}
210
+
211
+ # Get profiler reports
212
+ try:
213
+ profiler_base = resolver.get_base_report_path("profiler")
214
+ if profiler_base.exists():
215
+ for report_dir in profiler_base.iterdir():
216
+ if report_dir.is_dir():
217
+ db_file = report_dir / current_app.config["SQLITE_DB_PATH"]
218
+ if db_file.exists():
219
+ reports["profiler"].append(
220
+ {
221
+ "name": report_dir.name,
222
+ "path": str(report_dir),
223
+ "modified": report_dir.stat().st_mtime,
224
+ }
225
+ )
226
+ except Exception as e:
227
+ logger.warning(f"Error reading profiler reports: {e}")
228
+
229
+ # Get performance reports
230
+ try:
231
+ performance_base = resolver.get_base_report_path("performance")
232
+ if performance_base.exists():
233
+ for report_dir in performance_base.iterdir():
234
+ if report_dir.is_dir():
235
+ # Check for typical performance files
236
+ has_perf_files = any(
237
+ (report_dir / filename).exists()
238
+ for filename in [
239
+ "profile_log_device.csv",
240
+ "tracy_profile_log_host.tracy",
241
+ ]
242
+ ) or any(report_dir.glob("ops_perf_results*.csv"))
243
+
244
+ if has_perf_files:
245
+ reports["performance"].append(
246
+ {
247
+ "name": report_dir.name,
248
+ "path": str(report_dir),
249
+ "modified": report_dir.stat().st_mtime,
250
+ }
251
+ )
252
+ except Exception as e:
253
+ logger.warning(f"Error reading performance reports: {e}")
254
+
255
+ # Sort by modification time (newest first)
256
+ reports["profiler"].sort(key=lambda x: x["modified"], reverse=True)
257
+ reports["performance"].sort(key=lambda x: x["modified"], reverse=True)
258
+
259
+ return reports
98
260
 
99
261
 
100
262
  def get_npe_path(npe_name, current_app):
ttnn_visualizer/views.py CHANGED
@@ -12,6 +12,7 @@ from http import HTTPStatus
12
12
  from pathlib import Path
13
13
  from typing import List
14
14
 
15
+ import orjson
15
16
  import yaml
16
17
  import zstd
17
18
  from flask import Blueprint, Response, current_app, jsonify, request, session
@@ -68,6 +69,7 @@ from ttnn_visualizer.sftp_operations import (
68
69
  )
69
70
  from ttnn_visualizer.ssh_client import SSHClient
70
71
  from ttnn_visualizer.utils import (
72
+ create_path_resolver,
71
73
  get_cluster_descriptor_path,
72
74
  read_last_synced_file,
73
75
  timer,
@@ -368,20 +370,18 @@ def get_operation_buffers(operation_id, instance: Instance):
368
370
  @api.route("/profiler", methods=["GET"])
369
371
  @with_instance
370
372
  def get_profiler_data_list(instance: Instance):
371
- # Doesn't handle remote at the moment
372
- # is_remote = True if instance.remote_connection else False
373
- # config_key = "REMOTE_DATA_DIRECTORY" if is_remote else "LOCAL_DATA_DIRECTORY"
374
- config_key = "LOCAL_DATA_DIRECTORY"
375
- data_directory = Path(current_app.config[config_key])
373
+ # Use PathResolver to get the base path for profiler reports
374
+ resolver = create_path_resolver(current_app)
376
375
 
377
- # if is_remote:
378
- # connection = RemoteConnection.model_validate(instance.remote_connection, strict=False)
379
- # path = data_directory / connection.host / current_app.config["PROFILER_DIRECTORY_NAME"]
380
- # else:
381
- path = data_directory / current_app.config["PROFILER_DIRECTORY_NAME"]
376
+ # Note: "profiler" in app terminology maps to tt-metal's ttnn/reports
377
+ path = resolver.get_base_report_path("profiler", instance.remote_connection)
382
378
 
383
379
  if not path.exists():
384
- path.mkdir(parents=True, exist_ok=True)
380
+ if resolver.is_direct_report_mode:
381
+ logger.warning(f"TT-Metal profiler reports not found: {path}")
382
+ return jsonify([])
383
+ else:
384
+ path.mkdir(parents=True, exist_ok=True)
385
385
 
386
386
  valid_dirs = []
387
387
 
@@ -437,7 +437,6 @@ def get_profiler_data_list(instance: Instance):
437
437
  continue
438
438
  if not any(file.name == "config.json" for file in files):
439
439
  continue
440
-
441
440
  valid_dirs.append({"path": dir_path.name, "reportName": report_name})
442
441
 
443
442
  return jsonify(valid_dirs)
@@ -491,13 +490,20 @@ def delete_profiler_report(profiler_name, instance: Instance):
491
490
  @api.route("/performance", methods=["GET"])
492
491
  @with_instance
493
492
  def get_performance_data_list(instance: Instance):
493
+ # Use PathResolver to get the base path for performance reports
494
+ resolver = create_path_resolver(current_app)
495
+
496
+ # Note: "performance" in app terminology maps to tt-metal's profiler/reports
497
+ path = resolver.get_base_report_path("performance", instance.remote_connection)
498
+
494
499
  is_remote = True if instance.remote_connection else False
495
- config_key = "REMOTE_DATA_DIRECTORY" if is_remote else "LOCAL_DATA_DIRECTORY"
496
- data_directory = Path(current_app.config[config_key])
497
- path = data_directory / current_app.config["PERFORMANCE_DIRECTORY_NAME"]
498
500
 
499
- if not is_remote and not path.exists():
500
- path.mkdir(parents=True, exist_ok=True)
501
+ if not path.exists():
502
+ if resolver.is_direct_report_mode:
503
+ logger.warning(f"TT-Metal performance reports not found: {path}")
504
+ return jsonify([])
505
+ elif not is_remote:
506
+ path.mkdir(parents=True, exist_ok=True)
501
507
 
502
508
  if current_app.config["SERVER_MODE"]:
503
509
  session_instances = session.get("instances", [])
@@ -521,15 +527,7 @@ def get_performance_data_list(instance: Instance):
521
527
  set(db_directory_names + session_directory_names + demo_directory_names)
522
528
  )
523
529
  else:
524
- if is_remote:
525
- connection = RemoteConnection.model_validate(
526
- instance.remote_connection, strict=False
527
- )
528
- path = (
529
- data_directory
530
- / connection.host
531
- / current_app.config["PERFORMANCE_DIRECTORY_NAME"]
532
- )
530
+ # PathResolver already handles remote vs local logic
533
531
  directory_names = (
534
532
  [directory.name for directory in path.iterdir() if directory.is_dir()]
535
533
  if path.exists()
@@ -868,12 +866,10 @@ def create_npe_files():
868
866
  data_directory = current_app.config["LOCAL_DATA_DIRECTORY"]
869
867
 
870
868
  for file in files:
871
- if not file.filename.endswith(".json") and not file.filename.endswith(
872
- ".npeviz.zst"
873
- ):
869
+ if not file.filename.endswith(".json") and not file.filename.endswith(".zst"):
874
870
  return StatusMessage(
875
871
  status=ConnectionTestStates.FAILED,
876
- message="NPE requires a valid .json or .npeviz.zst file",
872
+ message="NPE requires a valid .json or .zst file",
877
873
  ).model_dump()
878
874
 
879
875
  npe_name = extract_npe_name(files)
@@ -1275,4 +1271,67 @@ def get_npe_data(instance: Instance):
1275
1271
  with open(uncompressed_path, "r") as file:
1276
1272
  npe_data = json.load(file)
1277
1273
 
1278
- return jsonify(npe_data)
1274
+ # Use orjson for much faster JSON serialization of large files
1275
+ return Response(orjson.dumps(npe_data), mimetype="application/json")
1276
+
1277
+
1278
+ @api.route("/notify", methods=["POST"])
1279
+ def notify_report_update():
1280
+ """
1281
+ Endpoint to receive notifications about report updates and broadcast them via websockets.
1282
+ """
1283
+ from ttnn_visualizer.sockets import (
1284
+ ExitStatus,
1285
+ ReportGenerated,
1286
+ emit_report_generated,
1287
+ )
1288
+
1289
+ try:
1290
+ data = request.get_json()
1291
+ if not data:
1292
+ return jsonify({"error": "No JSON data provided"}), 400
1293
+
1294
+ report_name = data.get("report_name")
1295
+ exit_status_str = data.get("exit_status")
1296
+
1297
+ if not report_name:
1298
+ return jsonify({"error": "report_name is required"}), 400
1299
+
1300
+ # Validate status
1301
+ try:
1302
+ exit_status = (
1303
+ ExitStatus(exit_status_str.upper()) if exit_status_str else None
1304
+ )
1305
+ except ValueError:
1306
+ return (
1307
+ jsonify({"error": "Invalid exit_status."}),
1308
+ 400,
1309
+ )
1310
+
1311
+ # Create and emit the report update
1312
+ report_generated = ReportGenerated(
1313
+ report_name=report_name,
1314
+ exit_status=exit_status,
1315
+ profiler_path=data.get("profiler_path"),
1316
+ performance_path=data.get("performance_path"),
1317
+ )
1318
+ emit_report_generated(report_generated)
1319
+
1320
+ logger.info(f"Report generated notification processed: {report_name}")
1321
+
1322
+ return (
1323
+ jsonify(
1324
+ {
1325
+ "report_name": report_name,
1326
+ "profiler_path": report_generated.profiler_path,
1327
+ "performance_path": report_generated.performance_path,
1328
+ "exit_status": exit_status.value if exit_status else None,
1329
+ "timestamp": report_generated.timestamp,
1330
+ }
1331
+ ),
1332
+ 200,
1333
+ )
1334
+
1335
+ except Exception as e:
1336
+ logger.error(f"Error processing report update notification: {str(e)}")
1337
+ return jsonify({"error": "Internal server error"}), 500
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ttnn_visualizer
3
- Version: 0.46.0
3
+ Version: 0.48.0
4
4
  Summary: TT-NN Visualizer
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -17,6 +17,7 @@ Requires-Dist: Flask-Static-Digest==0.4.1
17
17
  Requires-Dist: Flask==3.1.1
18
18
  Requires-Dist: gevent==24.10.2
19
19
  Requires-Dist: gunicorn~=23.0.0
20
+ Requires-Dist: orjson>=3.9.0
20
21
  Requires-Dist: pandas==2.2.3
21
22
  Requires-Dist: pydantic_core==2.27.1
22
23
  Requires-Dist: pydantic==2.10.3
@@ -1,31 +1,31 @@
1
1
  ttnn_visualizer/__init__.py,sha256=FCQeTWnXsf-Wx-fay53-lQsm0y5-GcPMUmzhE5upDx0,93
2
- ttnn_visualizer/app.py,sha256=q5Tb_69HawKdiw2uKe6_cOmYfvU5as40DoREvLfb_38,7281
3
- ttnn_visualizer/csv_queries.py,sha256=lSqjDiZiCVhTkxgkixRJjxvvHLPzzm6Lx8jZ8x4BoIA,15086
2
+ ttnn_visualizer/app.py,sha256=5LEFKR-jn5HGqzYU1OWE4LCHzS4OAzwLKge5jSRDsBc,8663
3
+ ttnn_visualizer/csv_queries.py,sha256=pQV3WJ0jSMo84L7kOdAbGO5lGfOtcq-oAlHzu09ND2Q,15089
4
4
  ttnn_visualizer/decorators.py,sha256=8k73rTiGPSpPP5CHxzLxTQPxoQTAlhMQNcEbplQL3Ek,5805
5
5
  ttnn_visualizer/enums.py,sha256=SEIqp1tlc_zw2vQ8nHH9YTaV0m3Cb8fjn_goqz5wurE,203
6
6
  ttnn_visualizer/exceptions.py,sha256=XwTIykJpdvZV8nqrd9JZdHIYL0EBFBhTbE9H09VZluA,2273
7
7
  ttnn_visualizer/extensions.py,sha256=6OIRJ8-_ccfjOaXSruRXiS29jEbxp4Pyk-0JlD8IHBQ,379
8
- ttnn_visualizer/file_uploads.py,sha256=05FzYjZZy1RHuGgFeJiAjtrpzYd6KcrZzpvIjBCUZss,5011
8
+ ttnn_visualizer/file_uploads.py,sha256=HFcC6TBt5I0oBkiKgM2Qw1W7hpixE8TOTACS5N-rmGE,5013
9
9
  ttnn_visualizer/instances.py,sha256=XctQgQXdlwtuXWFXFletRoX1m1lGUZdiW3TwIIjY0uw,11564
10
- ttnn_visualizer/models.py,sha256=oxZVvWjtBDP0X6GqoYaH4wDa5PqJF_vG_I3Q_YWHMmo,7814
11
- ttnn_visualizer/queries.py,sha256=3Nv0jXIDNVH-qKx9xc9zSINy4FdmDidu-1I6f-VYV48,9603
10
+ ttnn_visualizer/models.py,sha256=QCL64uynSS3WbUI05UoHIgex6eWgMGqf0-YTm1XwCwI,7854
11
+ ttnn_visualizer/queries.py,sha256=0s2zGA7CH1fbV6BWB-MhdHfWW7GhkDti4gVJyDmeCE8,9607
12
12
  ttnn_visualizer/remote_sqlite_setup.py,sha256=VdJk5LfkaJo1XPC-yxy909I0AOgJF1GUjryj0Oe0O14,3498
13
13
  ttnn_visualizer/serializers.py,sha256=LmjHIrFg8BLx1JKVFh9Nd_TcA7nyy1MwY2BOGnX1MKw,8029
14
- ttnn_visualizer/settings.py,sha256=k2EEjbQNR8khbl5IrOetBPhbqgLlqXvuhm0E2z9ImCM,4607
14
+ ttnn_visualizer/settings.py,sha256=W0PCeBCGXONNfFHqI7ATCVGhKv0a02-BhwBwrB3Clag,4660
15
15
  ttnn_visualizer/sftp_operations.py,sha256=9HwbPJPSO1UUQ98d5zeWAkEwR0zFPryUakcI68GqkVw,30181
16
- ttnn_visualizer/sockets.py,sha256=W5pK0QmlsU58EH_Qnra6HlcswLS7vsw5C_pk4avVYvs,3706
16
+ ttnn_visualizer/sockets.py,sha256=_Hdne33r4FrB2tg58Vw87FWLbgQ_ikICVp4o1Mkv2mo,4789
17
17
  ttnn_visualizer/ssh_client.py,sha256=-GS2_1tdlUqVoLfRS02i3_o1fQaM39UQN-jtAnPBmzQ,13511
18
- ttnn_visualizer/utils.py,sha256=MYCpvP9z8yoIVwI2Sa3iUahajZMLDxRmtRWrrUyB4_8,6223
19
- ttnn_visualizer/views.py,sha256=b1ayDuH7zTVr5Pi5KGkpLZMnUvX2pDjljFWDkumcCq0,43224
20
- ttnn_visualizer/static/index.html,sha256=RDJv0bYnRGaMh0KzFqsdaZd8OmO05JRyI-z2L1KSchE,1135
21
- ttnn_visualizer/static/assets/allPaths-esBqnTg5.js,sha256=pdwKU_Qg1xSwaKMha-qO5SOzutgGME6EvbxnWSe3PgI,255
22
- ttnn_visualizer/static/assets/allPathsLoader-KPOKJ-lr.js,sha256=f2t5H20m8LuOmh5qygz1a-sSLhHuLWXiGxTF9FargnM,477
18
+ ttnn_visualizer/utils.py,sha256=_W990vRnup9zlWJ-g_Bggyo-wDjCYF49p0nPxWNgxrE,12934
19
+ ttnn_visualizer/views.py,sha256=E5UFdbR8_lqHRPJmGrjq3S_F0Wu1WCsydWNihSUj9Fk,45133
20
+ ttnn_visualizer/static/index.html,sha256=PtUUC8PiSjaLZOgM7sFiII-ykqwrL1rX95MzjzYcXmc,1135
21
+ ttnn_visualizer/static/assets/allPaths-DyhSRH--.js,sha256=EUUj2FYiXwESHvwikbQ1n87byC2le5LLW8Q0LY3VyfM,255
22
+ ttnn_visualizer/static/assets/allPathsLoader-DXd_rN1a.js,sha256=eMyPpUy4eYuBbW1TRf5zx1fkA0ihMVzP_joOkP9GMow,477
23
23
  ttnn_visualizer/static/assets/index-03c8d4Gh.js,sha256=k0jIi5q-lzXcPCqAD7K091vBMOkJHmx_fYcYKh-fOnM,285602
24
- ttnn_visualizer/static/assets/index-BANm1CMY.js,sha256=uXWWiSs-Cs1MWW_pldHWmFOigc5b6WNH6lR_HC0pUGA,7880800
25
- ttnn_visualizer/static/assets/index-BuHal8Ii.css,sha256=YCXZxX68jwt682YZ5gMTPzmXN9r2NjHfItOsrCQqRXk,622571
24
+ ttnn_visualizer/static/assets/index-CZ0Uonoz.css,sha256=Xl6ASk5fzFtSKl55fxH-0Qw_RjPZC1aNvIqZmrzSdck,622981
26
25
  ttnn_visualizer/static/assets/index-PKNBViIU.js,sha256=dUuCyAPr_QvvTY0Xula4q4rgOm1J7xgdbppL67off4k,294225
26
+ ttnn_visualizer/static/assets/index-T8PVeTUn.js,sha256=1hk1rZB2-tBCp5WIQB_UZQDnbayuBQp2IX4s62i3-hY,7883860
27
27
  ttnn_visualizer/static/assets/site-BTBrvHC5.webmanifest,sha256=Uy_XmnGuYFVf-OZuma2NvgEPdrCrevb3HZvaxSIHoA0,456
28
- ttnn_visualizer/static/assets/splitPathsBySizeLoader-DYuDhweD.js,sha256=MWFWsPb9LjIyB4wpVSbMlOp3pN0673afNlKBfTZg-Dg,281
28
+ ttnn_visualizer/static/assets/splitPathsBySizeLoader-Gsi3qlIM.js,sha256=ssz5DwLHNfrtvO7Bji0ya9GLCkwQU9bYScLIErs2j5o,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
@@ -33,11 +33,11 @@ ttnn_visualizer/static/favicon/favicon.svg,sha256=wDPY3VrekJ_DE1TnJ2vUy602K3S4Xe
33
33
  ttnn_visualizer/static/sample-data/cluster-desc.yaml,sha256=LMxOmsRUXtVVU5ogzYkXUozB3dg2IzqIRJQpV_O5qMU,29618
34
34
  ttnn_visualizer/tests/__init__.py,sha256=FCQeTWnXsf-Wx-fay53-lQsm0y5-GcPMUmzhE5upDx0,93
35
35
  ttnn_visualizer/tests/test_queries.py,sha256=HqaDXwudZpXiigJdHkdJP8oiUc-PtHASbpLnQQpbD7A,13792
36
- ttnn_visualizer/tests/test_serializers.py,sha256=AF6m6tvewnZ_OSQMgMTUhsOI26GdJHPajvnRGIa9P4U,18492
37
- ttnn_visualizer-0.46.0.dist-info/licenses/LICENSE,sha256=WBbTfgMRePWa_1qrAP1iLhxywPnoSIbTAipSk1eeN6U,15301
38
- ttnn_visualizer-0.46.0.dist-info/licenses/LICENSE_understanding.txt,sha256=pymi-yb_RvYM9p2ZA4iSNsImcvhDBBxlGuJCY9dTq7M,233
39
- ttnn_visualizer-0.46.0.dist-info/METADATA,sha256=T7YviW1Jmjd5ymxtEbIdAhDCEV_9feKk61HHFYBOzKc,7751
40
- ttnn_visualizer-0.46.0.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
41
- ttnn_visualizer-0.46.0.dist-info/entry_points.txt,sha256=QpuUpkmQ_mEHJTMqOBdU0MH2Z4WF_9iFsGACeyyAO1E,61
42
- ttnn_visualizer-0.46.0.dist-info/top_level.txt,sha256=M1EGkvDOuIfbhDbcUdz2-TSdmCtDoQ2Uyag9k5JLDSY,16
43
- ttnn_visualizer-0.46.0.dist-info/RECORD,,
36
+ ttnn_visualizer/tests/test_serializers.py,sha256=IJekAZRBpyOr_Ffp0dqSrnhFOU_ZZ8pHma_JO0j23TQ,18762
37
+ ttnn_visualizer-0.48.0.dist-info/licenses/LICENSE,sha256=NQB3xoEB14Z4uKwzMDm2AZSYIcx4hZ5ZNgJNcIChWCo,19504
38
+ ttnn_visualizer-0.48.0.dist-info/licenses/LICENSE_understanding.txt,sha256=pymi-yb_RvYM9p2ZA4iSNsImcvhDBBxlGuJCY9dTq7M,233
39
+ ttnn_visualizer-0.48.0.dist-info/METADATA,sha256=k9gZwu0y6_VmfFxAUwmKwlSYYOkmv9Si--B3AVoMQoE,7780
40
+ ttnn_visualizer-0.48.0.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
41
+ ttnn_visualizer-0.48.0.dist-info/entry_points.txt,sha256=QpuUpkmQ_mEHJTMqOBdU0MH2Z4WF_9iFsGACeyyAO1E,61
42
+ ttnn_visualizer-0.48.0.dist-info/top_level.txt,sha256=M1EGkvDOuIfbhDbcUdz2-TSdmCtDoQ2Uyag9k5JLDSY,16
43
+ ttnn_visualizer-0.48.0.dist-info/RECORD,,