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
35Notes:
46 - Only Linux is supported for now (TODO: add support for other profilers)
2325 CFLAGS="-O2 -g -fno-omit-frame-pointer"
2426"""
2527
28+ from __future__ import annotations
29+
2630import argparse
2731import glob
2832import os
4145TARGET_DIR = "mypy.profile.tmpdir"
4246
4347
44- def _profile_self_check (target_dir : str ) -> None :
48+ def _profile_type_check (target_dir : str , code : str | None ) -> None :
4549 cache_dir = os .path .join (target_dir , ".mypy_cache" )
4650 if os .path .exists (cache_dir ):
4751 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
52+ args = []
53+ if code is None :
54+ args .extend (["--config-file" , "mypy_self_check.ini" ])
55+ for pat in "mypy/*.py" , "mypy/*/*.py" , "mypyc/*.py" , "mypyc/test/*.py" :
56+ args .extend (glob .glob (pat ))
57+ else :
58+ args .extend (["-c" , code ])
59+ check_cmd = ["python" , "-m" , "mypy" ] + args
60+ cmdline = ["perf" , "record" , "-g" ] + check_cmd
5361 t0 = time .time ()
5462 subprocess .run (cmdline , cwd = target_dir , check = True )
5563 elapsed = time .time () - t0
5664 print (f"{ elapsed :.2f} s elapsed" )
5765
5866
59- def profile_self_check (target_dir : str ) -> None :
67+ def profile_type_check (target_dir : str , code : str | None ) -> None :
6068 try :
61- _profile_self_check (target_dir )
69+ _profile_type_check (target_dir , code )
6270 except subprocess .CalledProcessError :
6371 print ("\n Profiling failed! You may missing some permissions." )
6472 print ("\n This may help (note that it has security implications):" )
@@ -92,7 +100,7 @@ def main() -> None:
92100 check_requirements ()
93101
94102 parser = argparse .ArgumentParser (
95- description = "Compile mypy and profile self checking using 'perf'."
103+ description = "Compile mypy and profile type checking using 'perf' (by default, self check) ."
96104 )
97105 parser .add_argument (
98106 "--multi-file" ,
@@ -102,9 +110,17 @@ def main() -> None:
102110 parser .add_argument (
103111 "--skip-compile" , action = "store_true" , help = "use compiled mypy from previous run"
104112 )
113+ parser .add_argument (
114+ "-c" ,
115+ metavar = "CODE" ,
116+ default = None ,
117+ type = str ,
118+ help = "profile type checking Python code fragment instead of mypy self-check" ,
119+ )
105120 args = parser .parse_args ()
106121 multi_file : bool = args .multi_file
107122 skip_compile : bool = args .skip_compile
123+ code : str | None = args .c
108124
109125 target_dir = TARGET_DIR
110126
@@ -116,7 +132,7 @@ def main() -> None:
116132 elif not os .path .isdir (target_dir ):
117133 sys .exit ("error: Can't find compile mypy from previous run -- can't use --skip-compile" )
118134
119- profile_self_check (target_dir )
135+ profile_type_check (target_dir , code )
120136
121137 print ()
122138 print ('NOTE: Compile CPython using CFLAGS="-O2 -g -fno-omit-frame-pointer" for good results' )
0 commit comments