ttnn-visualizer 0.48.0__py3-none-any.whl → 0.50.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/csv_queries.py +20 -13
  2. ttnn_visualizer/pytest_plugin.py +93 -0
  3. ttnn_visualizer/static/assets/allPaths-FfZB-oxi.js +1 -0
  4. ttnn_visualizer/static/assets/allPathsLoader-icaZ0D6C.js +2 -0
  5. ttnn_visualizer/static/assets/{index-T8PVeTUn.js → index-A5WDVH6-.js} +259 -259
  6. ttnn_visualizer/static/assets/index-CnPrfHYh.js +1 -0
  7. ttnn_visualizer/static/assets/index-Cnc1EkDo.js +1 -0
  8. ttnn_visualizer/static/assets/index-UWmN5XEZ.css +7 -0
  9. ttnn_visualizer/static/assets/splitPathsBySizeLoader-BtDN14Er.js +1 -0
  10. ttnn_visualizer/static/index.html +2 -2
  11. ttnn_visualizer/views.py +127 -59
  12. {ttnn_visualizer-0.48.0.dist-info → ttnn_visualizer-0.50.0.dist-info}/METADATA +2 -2
  13. {ttnn_visualizer-0.48.0.dist-info → ttnn_visualizer-0.50.0.dist-info}/RECORD +18 -17
  14. {ttnn_visualizer-0.48.0.dist-info → ttnn_visualizer-0.50.0.dist-info}/licenses/LICENSE +12 -5
  15. ttnn_visualizer/static/assets/allPaths-DyhSRH--.js +0 -1
  16. ttnn_visualizer/static/assets/allPathsLoader-DXd_rN1a.js +0 -2
  17. ttnn_visualizer/static/assets/index-03c8d4Gh.js +0 -1
  18. ttnn_visualizer/static/assets/index-CZ0Uonoz.css +0 -7
  19. ttnn_visualizer/static/assets/index-PKNBViIU.js +0 -1
  20. ttnn_visualizer/static/assets/splitPathsBySizeLoader-Gsi3qlIM.js +0 -1
  21. {ttnn_visualizer-0.48.0.dist-info → ttnn_visualizer-0.50.0.dist-info}/WHEEL +0 -0
  22. {ttnn_visualizer-0.48.0.dist-info → ttnn_visualizer-0.50.0.dist-info}/entry_points.txt +0 -0
  23. {ttnn_visualizer-0.48.0.dist-info → ttnn_visualizer-0.50.0.dist-info}/licenses/LICENSE_understanding.txt +0 -0
  24. {ttnn_visualizer-0.48.0.dist-info → ttnn_visualizer-0.50.0.dist-info}/top_level.txt +0 -0
@@ -14,7 +14,7 @@ import pandas as pd
14
14
  import zstd
15
15
  from tt_perf_report import perf_report
16
16
  from ttnn_visualizer.exceptions import DataFormatError
17
- from ttnn_visualizer.models import Instance, RemoteConnection
17
+ from ttnn_visualizer.models import Instance
18
18
 
19
19
 
20
20
  class LocalCSVQueryRunner:
@@ -433,18 +433,25 @@ class OpsPerformanceReportQueries:
433
433
  raw_csv = OpsPerformanceQueries.get_raw_csv(instance)
434
434
  csv_file = StringIO(raw_csv)
435
435
  csv_output_file = tempfile.mktemp(suffix=".csv")
436
- perf_report.generate_perf_report(
437
- csv_file,
438
- cls.DEFAULT_SIGNPOST,
439
- cls.DEFAULT_IGNORE_SIGNPOSTS,
440
- cls.DEFAULT_MIN_PERCENTAGE,
441
- cls.DEFAULT_ID_RANGE,
442
- csv_output_file,
443
- cls.DEFAULT_NO_ADVICE,
444
- cls.DEFAULT_TRACING_MODE,
445
- True,
446
- True,
447
- )
436
+
437
+ try:
438
+ perf_report.generate_perf_report(
439
+ csv_file,
440
+ cls.DEFAULT_SIGNPOST,
441
+ cls.DEFAULT_IGNORE_SIGNPOSTS,
442
+ cls.DEFAULT_MIN_PERCENTAGE,
443
+ cls.DEFAULT_ID_RANGE,
444
+ csv_output_file,
445
+ cls.DEFAULT_NO_ADVICE,
446
+ cls.DEFAULT_TRACING_MODE,
447
+ True,
448
+ True,
449
+ True,
450
+ True,
451
+ False,
452
+ )
453
+ except Exception as e:
454
+ raise DataFormatError(f"Error generating performance report: {e}") from e
448
455
 
449
456
  ops_perf_results = []
450
457
  ops_perf_results_reader = csv.DictReader(StringIO(raw_csv))
@@ -0,0 +1,93 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ #
3
+ # SPDX-FileCopyrightText: © 2025 Tenstorrent AI ULC
4
+ import json
5
+ import os
6
+ import urllib
7
+
8
+ try:
9
+ import ttnn
10
+ from loguru import logger
11
+ from tt_metal.tools.profiler.common import PROFILER_OUTPUT_DIR
12
+ except ImportError:
13
+ raise Exception("TT-Metal environment not found")
14
+
15
+
16
+ def pytest_runtest_makereport(item, call):
17
+ if call.when != "call":
18
+ return
19
+
20
+ webhook_url = os.environ.get("TTNN_VISUALIZER_WEBHOOK_URL", "").strip()
21
+
22
+ if not webhook_url:
23
+ webhook_url = "http://localhost:8000/api/notify"
24
+
25
+ status_str = _get_test_status_from_call(call)
26
+ _notify_visualizer_webhook(status_str, webhook_url)
27
+
28
+
29
+ def _notify_visualizer_webhook(status_str: str, webhook_url: str) -> None:
30
+ """POST JSON to the visualizer webhook endpoint."""
31
+ payload = {
32
+ "report_name": _get_ttnn_report_name(),
33
+ "profiler_path": _get_profiler_path(),
34
+ "performance_path": _get_performance_path(),
35
+ "status": status_str,
36
+ }
37
+
38
+ data = json.dumps(payload).encode("utf-8")
39
+ headers = {"Content-Type": "application/json"}
40
+ try:
41
+ request = urllib.request.Request(
42
+ webhook_url, data=data, headers=headers, method="POST"
43
+ )
44
+ logger.info(f"Posting report to TTNN-Visualizer: {payload}")
45
+ urllib.request.urlopen(request, timeout=2)
46
+ except urllib.error.HTTPError as error:
47
+ logger.error(
48
+ f"Error posting report to TTNN-Visualizer: {error.status} {error.reason}"
49
+ )
50
+ except Exception as err:
51
+ logger.error(err)
52
+
53
+
54
+ def _get_test_status_from_call(call) -> str:
55
+ """Determine test status from the call object."""
56
+ if call.excinfo is None:
57
+ return "PASS"
58
+ elif call.excinfo[0] == AssertionError:
59
+ return "FAIL"
60
+ else:
61
+ return "ERROR"
62
+
63
+
64
+ def _get_ttnn_report_name() -> str:
65
+ name = ttnn.CONFIG.report_name
66
+ return str(name) if name else "Not Available"
67
+
68
+
69
+ def _get_profiler_path() -> str:
70
+ tt_metal_home = os.getenv("TT_METAL_HOME", "")
71
+ return f"{tt_metal_home}/{ttnn.CONFIG.report_path}"
72
+
73
+
74
+ def _get_performance_path() -> str:
75
+ output_dir = PROFILER_OUTPUT_DIR
76
+
77
+ if os.getenv("TT_METAL_DEVICE_PROFILER", None) != "1":
78
+ return None
79
+
80
+ try:
81
+ directories = [item for item in output_dir.iterdir() if item.is_dir()]
82
+
83
+ if not directories:
84
+ return None
85
+
86
+ # Find the newest directory by modification time
87
+ newest_dir = max(directories, key=lambda d: d.stat().st_mtime)
88
+ return str(newest_dir)
89
+
90
+ except (OSError, ValueError):
91
+ return None
92
+
93
+ return str(output_dir)
@@ -0,0 +1 @@
1
+ import{I as s}from"./index-CnPrfHYh.js";import{I as r}from"./index-Cnc1EkDo.js";import{p as n,I as c}from"./index-A5WDVH6-.js";function p(t,a){const o=n(t);return a===c.STANDARD?s[o]:r[o]}export{s as IconSvgPaths16,r as IconSvgPaths20,p as getIconPaths};
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/allPaths-FfZB-oxi.js","assets/index-CnPrfHYh.js","assets/index-Cnc1EkDo.js","assets/index-A5WDVH6-.js","assets/index-UWmN5XEZ.css"])))=>i.map(i=>d[i]);
2
+ import{_ as e}from"./index-A5WDVH6-.js";const s=async(t,a)=>{const{getIconPaths:o}=await e(async()=>{const{getIconPaths:r}=await import("./allPaths-FfZB-oxi.js");return{getIconPaths:r}},__vite__mapDeps([0,1,2,3,4]));return o(t,a)};export{s as allPathsLoader};