Skip to content

Commit f5e670b

Browse files
committed
Support -c 'code fragment' to type check arbitrary code
1 parent 7680d7a commit f5e670b

File tree

1 file changed

+25
-11
lines changed

1 file changed

+25
-11
lines changed

misc/profile_check.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
"""Compile mypy using mypyc and profile self-check using perf.
1+
"""Compile mypy using mypyc and profile type checking using perf.
2+
3+
By default does a self check.
24
35
Notes:
46
- Only Linux is supported for now (TODO: add support for other profilers)
@@ -41,24 +43,28 @@
4143
TARGET_DIR = "mypy.profile.tmpdir"
4244

4345

44-
def _profile_self_check(target_dir: str) -> None:
46+
def _profile_type_check(target_dir: str, code: str | None) -> None:
4547
cache_dir = os.path.join(target_dir, ".mypy_cache")
4648
if os.path.exists(cache_dir):
4749
shutil.rmtree(cache_dir)
48-
files = []
49-
for pat in "mypy/*.py", "mypy/*/*.py", "mypyc/*.py", "mypyc/test/*.py":
50-
files.extend(glob.glob(pat))
51-
self_check_cmd = ["python", "-m", "mypy", "--config-file", "mypy_self_check.ini"] + files
52-
cmdline = ["perf", "record", "-g"] + self_check_cmd
50+
args = []
51+
if code is None:
52+
args.extend(["--config-file", "mypy_self_check.ini"])
53+
for pat in "mypy/*.py", "mypy/*/*.py", "mypyc/*.py", "mypyc/test/*.py":
54+
args.extend(glob.glob(pat))
55+
else:
56+
args.extend(["-c", code])
57+
check_cmd = ["python", "-m", "mypy"] + args
58+
cmdline = ["perf", "record", "-g"] + check_cmd
5359
t0 = time.time()
5460
subprocess.run(cmdline, cwd=target_dir, check=True)
5561
elapsed = time.time() - t0
5662
print(f"{elapsed:.2f}s elapsed")
5763

5864

59-
def profile_self_check(target_dir: str) -> None:
65+
def profile_type_check(target_dir: str, code: str | None) -> None:
6066
try:
61-
_profile_self_check(target_dir)
67+
_profile_type_check(target_dir, code)
6268
except subprocess.CalledProcessError:
6369
print("\nProfiling failed! You may missing some permissions.")
6470
print("\nThis may help (note that it has security implications):")
@@ -92,7 +98,7 @@ def main() -> None:
9298
check_requirements()
9399

94100
parser = argparse.ArgumentParser(
95-
description="Compile mypy and profile self checking using 'perf'."
101+
description="Compile mypy and profile type checking using 'perf' (by default, self check)."
96102
)
97103
parser.add_argument(
98104
"--multi-file",
@@ -102,9 +108,17 @@ def main() -> None:
102108
parser.add_argument(
103109
"--skip-compile", action="store_true", help="use compiled mypy from previous run"
104110
)
111+
parser.add_argument(
112+
"-c",
113+
metavar="CODE",
114+
default=None,
115+
type=str,
116+
help="profile type checking Python code fragment instead of mypy self-check",
117+
)
105118
args = parser.parse_args()
106119
multi_file: bool = args.multi_file
107120
skip_compile: bool = args.skip_compile
121+
code: str | None = args.c
108122

109123
target_dir = TARGET_DIR
110124

@@ -116,7 +130,7 @@ def main() -> None:
116130
elif not os.path.isdir(target_dir):
117131
sys.exit("error: Can't find compile mypy from previous run -- can't use --skip-compile")
118132

119-
profile_self_check(target_dir)
133+
profile_type_check(target_dir, code)
120134

121135
print()
122136
print('NOTE: Compile CPython using CFLAGS="-O2 -g -fno-omit-frame-pointer" for good results')

0 commit comments

Comments
 (0)