History

perf flamegraph: Fix minor pylint/type hint issues

Switch to assuming python3. Fix minor pylint issues on line length, repeated compares, not using f-strings and variable case. Add type hints and check with mypy.

Ian Rogers committed 1 year ago

Commit 95d692f1 parent 8db1d771 file · +33 −28Browse files

Showing the changes to tools/perf/scripts/python (1 of 1 file). Show all

Unified · Split

tools/perf/scripts/python/flamegraph.py+33−28
@@ -18,7 +18,6 @@ · 17 unmodified lines
1818 # pylint: disable=missing-class-docstring
1919 # pylint: disable=missing-function-docstring
2020
21−from __future__ import print_function
2221 import argparse
2322 import hashlib
2423 import io
@@ -26,9 +25,10 @@ import json · 1 unmodified line
2625 import os
2726 import subprocess
2827 import sys
28+from typing import Dict, Optional, Union
2929 import urllib.request
3030
31−minimal_html = """<head>
31+MINIMAL_HTML = """<head>
3232 <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/d3-flame-graph@4.1.3/dist/d3-flamegraph.css">
3333 </head>
3434 <body>
@@ -50,20 +50,20 @@ minimal_html = """<head> · 15 unmodified lines
5050
5151 # pylint: disable=too-few-public-methods
5252 class Node:
53− def __init__(self, name, libtype):
53+ def __init__(self, name: str, libtype: str):
5454 self.name = name
5555 # "root" | "kernel" | ""
5656 # "" indicates user space
5757 self.libtype = libtype
58− self.value = 0
59− self.children = []
58+ self.value: int = 0
59+ self.children: list[Node] = []
6060
61− def to_json(self):
61+ def to_json(self) -> Dict[str, Union[str, int, list[Dict]]]:
6262 return {
6363 "n": self.name,
6464 "l": self.libtype,
6565 "v": self.value,
66− "c": self.children
66+ "c": [x.to_json() for x in self.children]
6767 }
6868
6969
@@ -73,7 +73,7 @@ class FlameGraphCLI: · 3 unmodified lines
7373 self.stack = Node("all", "root")
7474
7575 @staticmethod
76− def get_libtype_from_dso(dso):
76+ def get_libtype_from_dso(dso: Optional[str]) -> str:
7777 """
7878 when kernel-debuginfo is installed,
7979 dso points to /usr/lib/debug/lib/modules/*/vmlinux
@@ -84,7 +84,7 @@ class FlameGraphCLI: · 4 unmodified lines
8484 return ""
8585
8686 @staticmethod
87− def find_or_create_node(node, name, libtype):
87+ def find_or_create_node(node: Node, name: str, libtype: str) -> Node:
8888 for child in node.children:
8989 if child.name == name:
9090 return child
@@ -93,7 +93,7 @@ class FlameGraphCLI: · 2 unmodified lines
9393 node.children.append(child)
9494 return child
9595
96− def process_event(self, event):
96+ def process_event(self, event) -> None:
9797 # ignore events where the event name does not match
9898 # the one specified by the user
9999 if self.args.event_name and event.get("ev_name") != self.args.event_name:
@@ -106,7 +106,7 @@ class FlameGraphCLI: · 6 unmodified lines
106106 comm = event["comm"]
107107 libtype = "kernel"
108108 else:
109− comm = "{} ({})".format(event["comm"], pid)
109+ comm = f"{event['comm']} ({pid})"
110110 libtype = ""
111111 node = self.find_or_create_node(self.stack, comm, libtype)
112112
@@ -121,7 +121,7 @@ class FlameGraphCLI: · 8 unmodified lines
121121 node = self.find_or_create_node(node, name, libtype)
122122 node.value += 1
123123
124− def get_report_header(self):
124+ def get_report_header(self) -> str:
125125 if self.args.input == "-":
126126 # when this script is invoked with "perf script flamegraph",
127127 # no perf.data is created and we cannot read the header of it
@@ -131,7 +131,8 @@ class FlameGraphCLI: · 3 unmodified lines
131131 # if the file name other than perf.data is given,
132132 # we read the header of that file
133133 if self.args.input:
134− output = subprocess.check_output(["perf", "report", "--header-only", "-i", self.args.input])
134+ output = subprocess.check_output(["perf", "report", "--header-only",
135+ "-i", self.args.input])
135136 else:
136137 output = subprocess.check_output(["perf", "report", "--header-only"])
137138
@@ -140,10 +141,10 @@ class FlameGraphCLI: · 2 unmodified lines
140141 result += "\nFocused event: " + self.args.event_name
141142 return result
142143 except Exception as err: # pylint: disable=broad-except
143− print("Error reading report header: {}".format(err), file=sys.stderr)
144+ print(f"Error reading report header: {err}", file=sys.stderr)
144145 return ""
145146
146− def trace_end(self):
147+ def trace_end(self) -> None:
147148 stacks_json = json.dumps(self.stack, default=lambda x: x.to_json())
148149
149150 if self.args.format == "html":
@@ -167,7 +168,8 @@ graph template (--template PATH) or use another output format (--format · 17 unmodified lines
167168 FORMAT).""",
168169 file=sys.stderr)
169170 if self.args.input == "-":
170− print("""Not attempting to download Flame Graph template as script command line
171+ print(
172+"""Not attempting to download Flame Graph template as script command line
171173 input is disabled due to using live mode. If you want to download the
172174 template retry without live mode. For example, use 'perf record -a -g
173175 -F 99 sleep 60' and 'perf script report flamegraph'. Alternatively,
@@ -176,37 +178,40 @@ https://cdn.jsdelivr.net/npm/d3-flame-graph@4.1.3/dist/templates/d3-flamegraph-b · 2 unmodified lines
176178 and place it at:
177179 /usr/share/d3-flame-graph/d3-flamegraph-base.html""",
178180 file=sys.stderr)
179− quit()
181+ sys.exit(1)
180182 s = None
181− while s != "y" and s != "n":
182− s = input("Do you wish to download a template from cdn.jsdelivr.net? (this warning can be suppressed with --allow-download) [yn] ").lower()
183+ while s not in ["y", "n"]:
184+ s = input("Do you wish to download a template from cdn.jsdelivr.net?" +
185+ "(this warning can be suppressed with --allow-download) [yn] "
186+ ).lower()
183187 if s == "n":
184− quit()
185− template = "https://cdn.jsdelivr.net/npm/d3-flame-graph@4.1.3/dist/templates/d3-flamegraph-base.html"
188+ sys.exit(1)
189+ template = ("https://cdn.jsdelivr.net/npm/d3-flame-graph@4.1.3/dist/templates/"
190+ "d3-flamegraph-base.html")
186191 template_md5sum = "143e0d06ba69b8370b9848dcd6ae3f36"
187192
188193 try:
189− with urllib.request.urlopen(template) as template:
194+ with urllib.request.urlopen(template) as url_template:
190195 output_str = "".join([
191− l.decode("utf-8") for l in template.readlines()
196+ l.decode("utf-8") for l in url_template.readlines()
192197 ])
193198 except Exception as err:
194199 print(f"Error reading template {template}: {err}\n"
195200 "a minimal flame graph will be generated", file=sys.stderr)
196− output_str = minimal_html
201+ output_str = MINIMAL_HTML
197202 template_md5sum = None
198203
199204 if template_md5sum:
200205 download_md5sum = hashlib.md5(output_str.encode("utf-8")).hexdigest()
201206 if download_md5sum != template_md5sum:
202207 s = None
203− while s != "y" and s != "n":
208+ while s not in ["y", "n"]:
204209 s = input(f"""Unexpected template md5sum.
205210 {download_md5sum} != {template_md5sum}, for:
206211 {output_str}
207212 continue?[yn] """).lower()
208213 if s == "n":
209− quit()
214+ sys.exit(1)
210215
211216 output_str = output_str.replace("/** @options_json **/", options_json)
212217 output_str = output_str.replace("/** @flamegraph_json **/", stacks_json)
@@ -220,12 +225,12 @@ continue?[yn] """).lower() · 7 unmodified lines
220225 with io.open(sys.stdout.fileno(), "w", encoding="utf-8", closefd=False) as out:
221226 out.write(output_str)
222227 else:
223− print("dumping data to {}".format(output_fn))
228+ print(f"dumping data to {output_fn}")
224229 try:
225230 with io.open(output_fn, "w", encoding="utf-8") as out:
226231 out.write(output_str)
227232 except IOError as err:
228− print("Error writing output file: {}".format(err), file=sys.stderr)
233+ print(f"Error writing output file: {err}", file=sys.stderr)
229234 sys.exit(1)
230235
231236

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t