11from __future__ import annotations
22
33import sys
4+ import warnings
45from typing import TYPE_CHECKING
56
67from pytest_codspeed import __semver_version__
1213
1314 from pytest import Session
1415
15- from pytest_codspeed .instruments import P , T
16+ from pytest_codspeed .config import PedanticOptions
17+ from pytest_codspeed .instruments import T
1618 from pytest_codspeed .plugin import BenchmarkMarkerOptions , CodSpeedConfig
1719
1820SUPPORTS_PERF_TRAMPOLINE = sys .version_info >= (3 , 12 )
@@ -52,9 +54,9 @@ def measure(
5254 marker_options : BenchmarkMarkerOptions ,
5355 name : str ,
5456 uri : str ,
55- fn : Callable [P , T ],
56- * args : P . args ,
57- ** kwargs : P . kwargs ,
57+ fn : Callable [... , T ],
58+ * args : tuple ,
59+ ** kwargs : dict [ str , Any ] ,
5860 ) -> T :
5961 self .benchmark_count += 1
6062
@@ -78,8 +80,54 @@ def __codspeed_root_frame__() -> T:
7880 self .instrument_hooks .lib .callgrind_stop_instrumentation ()
7981 self .instrument_hooks .set_executed_benchmark (uri )
8082
83+ def measure_pedantic (
84+ self ,
85+ marker_options : BenchmarkMarkerOptions ,
86+ pedantic_options : PedanticOptions [T ],
87+ name : str ,
88+ uri : str ,
89+ ) -> T :
90+ if pedantic_options .rounds != 1 or pedantic_options .iterations != 1 :
91+ warnings .warn (
92+ "Valgrind instrument ignores rounds and iterations settings "
93+ "in pedantic mode"
94+ )
95+ if not self .instrument_hooks :
96+ args , kwargs = pedantic_options .setup_and_get_args_kwargs ()
97+ out = pedantic_options .target (* args , ** kwargs )
98+ if pedantic_options .teardown is not None :
99+ pedantic_options .teardown (* args , ** kwargs )
100+ return out
101+
102+ def __codspeed_root_frame__ (* args , ** kwargs ) -> T :
103+ return pedantic_options .target (* args , ** kwargs )
104+
105+ # Warmup
106+ warmup_rounds = max (
107+ pedantic_options .warmup_rounds , 1 if SUPPORTS_PERF_TRAMPOLINE else 0
108+ )
109+ for _ in range (warmup_rounds ):
110+ args , kwargs = pedantic_options .setup_and_get_args_kwargs ()
111+ __codspeed_root_frame__ (* args , ** kwargs )
112+ if pedantic_options .teardown is not None :
113+ pedantic_options .teardown (* args , ** kwargs )
114+
115+ # Compute the actual result of the function
116+ args , kwargs = pedantic_options .setup_and_get_args_kwargs ()
117+ self .instrument_hooks .lib .callgrind_start_instrumentation ()
118+ try :
119+ out = __codspeed_root_frame__ (* args , ** kwargs )
120+ finally :
121+ self .instrument_hooks .lib .callgrind_stop_instrumentation ()
122+ self .instrument_hooks .set_executed_benchmark (uri )
123+ if pedantic_options .teardown is not None :
124+ pedantic_options .teardown (* args , ** kwargs )
125+
126+ return out
127+
81128 def report (self , session : Session ) -> None :
82129 reporter = session .config .pluginmanager .get_plugin ("terminalreporter" )
130+ assert reporter is not None , "terminalreporter not found"
83131 count_suffix = "benchmarked" if self .should_measure else "benchmark tested"
84132 reporter .write_sep (
85133 "=" ,
0 commit comments