mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v1] perf python: Fix ilist TreeNode string type drift
@ 2026-09-10 17:44 Ian Rogers
  2026-09-10 21:15 ` [PATCH v2] " Ian Rogers
  0 siblings, 1 reply; 3+ messages in thread
From: Ian Rogers @ 2026-09-10 17:44 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Jiri Olsa, Ian Rogers, Adrian Hunter, James Clark,
	linux-perf-users, linux-kernel

Updates Tree type hints to correctly use TreeNode[TreeValue]
across all assignments preventing mypy strictness mismatches.

Address some other minor stylistic issues reported by mypy, pylint and
Sashiko.

Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/python/ilist.py | 70 ++++++++++++++++++++------------------
 1 file changed, 37 insertions(+), 33 deletions(-)

diff --git a/tools/perf/python/ilist.py b/tools/perf/python/ilist.py
index 0d757ddb4795..4797818ef42e 100755
--- a/tools/perf/python/ilist.py
+++ b/tools/perf/python/ilist.py
@@ -6,7 +6,7 @@ from abc import ABC, abstractmethod
 import argparse
 from dataclasses import dataclass
 import math
-from typing import Any, Dict, Optional, Tuple
+from typing import Any, Dict, List, Optional, Set, Tuple
 import perf
 from textual import on
 from textual.app import App, ComposeResult
@@ -19,7 +19,7 @@ from textual.widgets import Button, Footer, Header, Input, Label, Sparkline, Sta
 from textual.widgets.tree import TreeNode
 
 
-def get_info(info: Dict[str, str], key: str):
+def get_info(info: Dict[str, Any], key: str):
     return (info[key] + "\n") if key in info else ""
 
 
@@ -234,7 +234,7 @@ class IListApp(App):
 
     def __init__(self, interval: float) -> None:
         self.interval = interval
-        self.evlist = None
+        self.evlist: Optional[perf.evlist] = None
         self.selected: Optional[TreeValue] = None
         self.search_results: list[TreeNode[TreeValue]] = []
         self.cur_search_result: TreeNode[TreeValue] | None = None
@@ -290,12 +290,12 @@ class IListApp(App):
             event = event.lower()
             search_label.update(f'Searching for events matching "{event}"')
 
-            tree: Tree[str] = self.query_one("#root", Tree)
+            tree: Tree[TreeValue] = self.query_one("#root", Tree)
 
-            def find_search_results(event: str, node: TreeNode[str],
+            def find_search_results(event: str, node: TreeNode[TreeValue],
                                     cursor_seen: bool = False,
-                                    match_after_cursor: Optional[TreeNode[str]] = None
-                                    ) -> Tuple[bool, Optional[TreeNode[str]]]:
+                                    match_after_cursor: Optional[TreeNode[TreeValue]] = None
+                                    ) -> Tuple[bool, Optional[TreeNode[TreeValue]]]:
                 """Find nodes that match the search remembering the one after the cursor."""
                 if not cursor_seen and node == tree.cursor_node:
                     cursor_seen = True
@@ -332,7 +332,7 @@ class IListApp(App):
 
     def action_collapse(self) -> None:
         """Collapse the part of the tree currently on."""
-        tree: Tree[str] = self.query_one("#root", Tree)
+        tree: Tree[TreeValue] = self.query_one("#root", Tree)
         node = tree.cursor_node
         if node and node.parent:
             node.parent.collapse_all()
@@ -343,31 +343,34 @@ class IListApp(App):
         if not self.selected or not self.evlist:
             return
 
-        def update_count(cpu: int, count: int):
+        def update_count(cpu: int, count: int | float):
             # Update the raw count display.
-            counter: Label = self.query(f"#counter_cpu{cpu}" if cpu >= 0 else "#counter_total")
-            if not counter:
+            counter_query = self.query(f"#counter_cpu{cpu}" if cpu >= 0 else "#counter_total")
+            if not counter_query:
                 return
-            counter = counter.first(Label)
+            counter: Label = counter_query.first(Label)
             counter.update(str(count))
 
             # Update the sparkline.
-            line: Sparkline = self.query(f"#sparkline_cpu{cpu}" if cpu >= 0 else "#sparkline_total")
-            if not line:
+            line_query = self.query(f"#sparkline_cpu{cpu}" if cpu >= 0 else "#sparkline_total")
+            if not line_query:
                 return
-            line = line.first(Sparkline)
+            line: Sparkline = line_query.first(Sparkline)
             # If there are more events than the width, remove the front event.
-            if len(line.data) > line.size.width:
-                line.data.pop(0)
-            line.data.append(count)
-            line.mutate_reactive(Sparkline.data)
+            if line.data is not None:
+                if len(line.data) > line.size.width:
+                    line.data = line.data[1:]
+                line.data = list(line.data) + [float(count)]
+            else:
+                line.data = [float(count)]
+            line.refresh()
 
         # Update the total and each CPU counts, assume there's just 1 evsel.
-        total = 0
+        total: float = 0.0
         self.evlist.disable()
         for evsel in self.evlist:
             for cpu in evsel.cpus():
-                aggr = 0
+                aggr: float = 0.0
                 for thread in evsel.threads():
                     aggr += self.selected.value(self.evlist, evsel, cpu, thread)
                 update_count(cpu, aggr)
@@ -424,16 +427,16 @@ class IListApp(App):
         # Add spark lines for all the CPUs. Note, must be done after
         # open so that the evlist CPUs have been computed by propagate
         # maps.
-        line = CounterSparkline(cpu=-1)
-        lines.mount(line)
+        line_sp = CounterSparkline(cpu=-1)
+        lines.mount(line_sp)
         for cpu in self.evlist.all_cpus():
-            line = CounterSparkline(cpu)
-            lines.mount(line)
-        line = Counter(cpu=-1)
-        lines.mount(line)
+            c_sp = CounterSparkline(cpu)
+            lines.mount(c_sp)
+        c_val = Counter(cpu=-1)
+        lines.mount(c_val)
         for cpu in self.evlist.all_cpus():
-            line = Counter(cpu)
-            lines.mount(line)
+            c_val2 = Counter(cpu)
+            lines.mount(c_val2)
 
     def compose(self) -> ComposeResult:
         """Draws the app."""
@@ -459,17 +462,18 @@ class IListApp(App):
                     # Reading events may fail with EPERM, ignore.
                     pass
             metrics = tree.root.add("Metrics")
-            groups = set()
+            groups: Set[str] = set()
             for metric in perf.metrics():
                 groups.update(metric["MetricGroup"])
 
-            def add_metrics_to_tree(node: TreeNode[TreeValue], parent: str, pmu: str = None):
+            def add_metrics_to_tree(node: TreeNode[TreeValue], parent: str, pmu: Optional[str] = None):
                 for metric in sorted(perf.metrics(), key=lambda x: x["MetricName"]):
-                    metric_pmu = metric.get('PMU')
+                    metric_pmu_raw = metric.get('PMU')
+                    metric_pmu = str(metric_pmu_raw) if metric_pmu_raw else ''
                     if pmu and metric_pmu and metric_pmu != pmu:
                         continue
                     if parent in metric["MetricGroup"]:
-                        name = metric["MetricName"]
+                        name = str(metric["MetricName"])
                         display_name = name
                         if metric_pmu:
                             display_name += f" ({metric_pmu})"
-- 
2.55.0.1007.g17ff1f9808-goog


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-09-13 21:40 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-10 17:44 [PATCH v1] perf python: Fix ilist TreeNode string type drift Ian Rogers
2026-09-10 21:15 ` [PATCH v2] " Ian Rogers
2026-09-13 21:40   ` Arnaldo Carvalho de Melo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®