pytest-codspeed 4.2.0__tar.gz → 4.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. {pytest_codspeed-4.2.0/src/pytest_codspeed.egg-info → pytest_codspeed-4.3.0}/PKG-INFO +9 -9
  2. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/README.md +8 -8
  3. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/pyproject.toml +6 -1
  4. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/__init__.py +2 -2
  5. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/__init__.py +14 -6
  6. pytest_codspeed-4.2.0/src/pytest_codspeed/instruments/valgrind.py → pytest_codspeed-4.3.0/src/pytest_codspeed/instruments/analysis.py +26 -10
  7. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/__init__.py +13 -1
  8. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/build.py +2 -0
  9. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/dist_instrument_hooks.pyi +2 -0
  10. pytest_codspeed-4.3.0/src/pytest_codspeed/instruments/hooks/instrument-hooks/dist/core.c +11220 -0
  11. pytest_codspeed-4.3.0/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/compat.h +36 -0
  12. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/core.h +1 -0
  13. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/instrument-hooks/scripts/release.py +4 -0
  14. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/walltime.py +36 -3
  15. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/plugin.py +12 -3
  16. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0/src/pytest_codspeed.egg-info}/PKG-INFO +9 -9
  17. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed.egg-info/SOURCES.txt +3 -1
  18. pytest_codspeed-4.3.0/tests/test_format_time.py +35 -0
  19. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/tests/test_pytest_plugin.py +1 -1
  20. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/tests/test_pytest_plugin_cpu_instrumentation.py +7 -9
  21. pytest_codspeed-4.2.0/src/pytest_codspeed/instruments/hooks/instrument-hooks/dist/core.c +0 -8638
  22. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/LICENSE +0 -0
  23. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/setup.cfg +0 -0
  24. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/setup.py +0 -0
  25. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/config.py +0 -0
  26. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/callgrind.h +0 -0
  27. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/valgrind.h +0 -0
  28. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/zig.h +0 -0
  29. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/py.typed +0 -0
  30. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/utils.py +0 -0
  31. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed.egg-info/dependency_links.txt +0 -0
  32. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed.egg-info/entry_points.txt +0 -0
  33. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed.egg-info/requires.txt +0 -0
  34. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/src/pytest_codspeed.egg-info/top_level.txt +0 -0
  35. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/tests/test_pytest_plugin_walltime.py +0 -0
  36. {pytest_codspeed-4.2.0 → pytest_codspeed-4.3.0}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytest-codspeed
3
- Version: 4.2.0
3
+ Version: 4.3.0
4
4
  Summary: Pytest plugin to create CodSpeed benchmarks
5
5
  Author-email: Arthur Pastel <arthur@codspeed.io>
6
6
  License: The MIT License (MIT)
@@ -60,7 +60,7 @@ Requires-Dist: pytest-xdist~=3.6.1; extra == "compat"
60
60
 
61
61
  [![CI](https://github.com/CodSpeedHQ/pytest-codspeed/actions/workflows/ci.yml/badge.svg)](https://github.com/CodSpeedHQ/pytest-codspeed/actions/workflows/ci.yml)
62
62
  [![PyPi Version](https://img.shields.io/pypi/v/pytest-codspeed?color=%2334D058&label=pypi)](https://pypi.org/project/pytest-codspeed)
63
- ![Python Version](https://img.shields.io/badge/python-3.9%20|%203.10%20|%203.11%20|%203.12%20|%203.13-informational.svg)
63
+ ![Python Version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-informational.svg)
64
64
  [![Discord](https://img.shields.io/badge/chat%20on-discord-7289da.svg)](https://discord.com/invite/MxpaCfKSqF)
65
65
  [![CodSpeed Badge](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/CodSpeedHQ/pytest-codspeed)
66
66
 
@@ -118,10 +118,10 @@ If you want to run the benchmarks tests locally, you can use the `--codspeed` py
118
118
  ```sh
119
119
  $ pytest tests/ --codspeed
120
120
  ============================= test session starts ====================
121
- platform darwin -- Python 3.13.0, pytest-7.4.4, pluggy-1.5.0
122
- codspeed: 3.0.0 (enabled, mode: walltime, timer_resolution: 41.7ns)
121
+ platform darwin -- Python 3.14.0, pytest-7.4.4, pluggy-1.5.0
122
+ codspeed: 4.2.0 (enabled, mode: walltime, timer_resolution: 41.7ns)
123
123
  rootdir: /home/user/codspeed-test, configfile: pytest.ini
124
- plugins: codspeed-3.0.0
124
+ plugins: codspeed-4.2.0
125
125
  collected 1 items
126
126
 
127
127
  tests/test_sum_squares.py . [ 100%]
@@ -159,10 +159,10 @@ jobs:
159
159
  name: Run benchmarks
160
160
  runs-on: ubuntu-latest
161
161
  steps:
162
- - uses: actions/checkout@v4
163
- - uses: actions/setup-python@v5
162
+ - uses: actions/checkout@v5
163
+ - uses: actions/setup-python@v6
164
164
  with:
165
- python-version: "3.13"
165
+ python-version: "3.14"
166
166
 
167
167
  - name: Install dependencies
168
168
  run: pip install -r requirements.txt
@@ -170,7 +170,7 @@ jobs:
170
170
  - name: Run benchmarks
171
171
  uses: CodSpeedHQ/action@v4
172
172
  with:
173
- mode: instrumentation # or `walltime`
173
+ mode: simulation # or `walltime`
174
174
  token: ${{ secrets.CODSPEED_TOKEN }}
175
175
  run: pytest tests/ --codspeed
176
176
  ```
@@ -3,7 +3,7 @@
3
3
 
4
4
  [![CI](https://github.com/CodSpeedHQ/pytest-codspeed/actions/workflows/ci.yml/badge.svg)](https://github.com/CodSpeedHQ/pytest-codspeed/actions/workflows/ci.yml)
5
5
  [![PyPi Version](https://img.shields.io/pypi/v/pytest-codspeed?color=%2334D058&label=pypi)](https://pypi.org/project/pytest-codspeed)
6
- ![Python Version](https://img.shields.io/badge/python-3.9%20|%203.10%20|%203.11%20|%203.12%20|%203.13-informational.svg)
6
+ ![Python Version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-informational.svg)
7
7
  [![Discord](https://img.shields.io/badge/chat%20on-discord-7289da.svg)](https://discord.com/invite/MxpaCfKSqF)
8
8
  [![CodSpeed Badge](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/CodSpeedHQ/pytest-codspeed)
9
9
 
@@ -61,10 +61,10 @@ If you want to run the benchmarks tests locally, you can use the `--codspeed` py
61
61
  ```sh
62
62
  $ pytest tests/ --codspeed
63
63
  ============================= test session starts ====================
64
- platform darwin -- Python 3.13.0, pytest-7.4.4, pluggy-1.5.0
65
- codspeed: 3.0.0 (enabled, mode: walltime, timer_resolution: 41.7ns)
64
+ platform darwin -- Python 3.14.0, pytest-7.4.4, pluggy-1.5.0
65
+ codspeed: 4.2.0 (enabled, mode: walltime, timer_resolution: 41.7ns)
66
66
  rootdir: /home/user/codspeed-test, configfile: pytest.ini
67
- plugins: codspeed-3.0.0
67
+ plugins: codspeed-4.2.0
68
68
  collected 1 items
69
69
 
70
70
  tests/test_sum_squares.py . [ 100%]
@@ -102,10 +102,10 @@ jobs:
102
102
  name: Run benchmarks
103
103
  runs-on: ubuntu-latest
104
104
  steps:
105
- - uses: actions/checkout@v4
106
- - uses: actions/setup-python@v5
105
+ - uses: actions/checkout@v5
106
+ - uses: actions/setup-python@v6
107
107
  with:
108
- python-version: "3.13"
108
+ python-version: "3.14"
109
109
 
110
110
  - name: Install dependencies
111
111
  run: pip install -r requirements.txt
@@ -113,7 +113,7 @@ jobs:
113
113
  - name: Run benchmarks
114
114
  uses: CodSpeedHQ/action@v4
115
115
  with:
116
- mode: instrumentation # or `walltime`
116
+ mode: simulation # or `walltime`
117
117
  token: ${{ secrets.CODSPEED_TOKEN }}
118
118
  run: pytest tests/ --codspeed
119
119
  ```
@@ -44,6 +44,11 @@ compat = [
44
44
  # "pytest-speed>=0.3.5",
45
45
  ]
46
46
 
47
+ [tool.uv]
48
+ # Python builds change with uv versions, and we are quite susceptible to that.
49
+ # We pin uv to to make sure reproducibility is maintained for any contributor.
50
+ required-version = "0.9.5"
51
+
47
52
  [tool.uv.sources]
48
53
  pytest-codspeed = { workspace = true }
49
54
 
@@ -72,7 +77,7 @@ version = { attr = "pytest_codspeed.__version__" }
72
77
 
73
78
 
74
79
  [tool.bumpver]
75
- current_version = "4.2.0"
80
+ current_version = "4.3.0"
76
81
  version_pattern = "MAJOR.MINOR.PATCH[-TAG[NUM]]"
77
82
  commit_message = "Release v{new_version} 🚀"
78
83
  tag_message = "Release v{new_version} 🚀"
@@ -1,6 +1,6 @@
1
- __version__ = "4.2.0"
1
+ __version__ = "4.3.0"
2
2
  # We also have the semver version since __version__ is not semver compliant
3
- __semver_version__ = "4.2.0"
3
+ __semver_version__ = "4.3.0"
4
4
 
5
5
  from .plugin import BenchmarkFixture
6
6
 
@@ -21,7 +21,7 @@ class Instrument(metaclass=ABCMeta):
21
21
  instrument: ClassVar[str]
22
22
 
23
23
  @abstractmethod
24
- def __init__(self, config: CodSpeedConfig): ...
24
+ def __init__(self, config: CodSpeedConfig, mode: MeasurementMode): ...
25
25
 
26
26
  @abstractmethod
27
27
  def get_instrument_config_str_and_warns(self) -> tuple[str, list[str]]: ...
@@ -56,17 +56,25 @@ class Instrument(metaclass=ABCMeta):
56
56
 
57
57
 
58
58
  class MeasurementMode(str, Enum):
59
- Instrumentation = "instrumentation"
59
+ Simulation = "simulation"
60
+ Memory = "memory"
60
61
  WallTime = "walltime"
61
62
 
63
+ @classmethod
64
+ def _missing_(cls, value: object):
65
+ # Accept "instrumentation" as deprecated alias for "simulation"
66
+ if value == "instrumentation":
67
+ return cls.Simulation
68
+ return None
69
+
62
70
 
63
71
  def get_instrument_from_mode(mode: MeasurementMode) -> type[Instrument]:
64
- from pytest_codspeed.instruments.valgrind import (
65
- ValgrindInstrument,
72
+ from pytest_codspeed.instruments.analysis import (
73
+ AnalysisInstrument,
66
74
  )
67
75
  from pytest_codspeed.instruments.walltime import WallTimeInstrument
68
76
 
69
- if mode == MeasurementMode.Instrumentation:
70
- return ValgrindInstrument
77
+ if mode in (MeasurementMode.Simulation, MeasurementMode.Memory):
78
+ return AnalysisInstrument
71
79
  else:
72
80
  return WallTimeInstrument
@@ -6,7 +6,10 @@ from typing import TYPE_CHECKING
6
6
 
7
7
  from pytest_codspeed import __semver_version__
8
8
  from pytest_codspeed.instruments import Instrument
9
- from pytest_codspeed.instruments.hooks import InstrumentHooks
9
+ from pytest_codspeed.instruments.hooks import (
10
+ FEATURE_DISABLE_CALLGRIND_MARKERS,
11
+ InstrumentHooks,
12
+ )
10
13
  from pytest_codspeed.utils import SUPPORTS_PERF_TRAMPOLINE
11
14
 
12
15
  if TYPE_CHECKING:
@@ -15,15 +18,17 @@ if TYPE_CHECKING:
15
18
  from pytest import Session
16
19
 
17
20
  from pytest_codspeed.config import PedanticOptions
18
- from pytest_codspeed.instruments import P, T
21
+ from pytest_codspeed.instruments import MeasurementMode, P, T
19
22
  from pytest_codspeed.plugin import BenchmarkMarkerOptions, CodSpeedConfig
20
23
 
21
24
 
22
- class ValgrindInstrument(Instrument):
23
- instrument = "valgrind"
25
+ class AnalysisInstrument(Instrument):
26
+ instrument = "analysis"
24
27
  instrument_hooks: InstrumentHooks | None
28
+ mode: MeasurementMode
25
29
 
26
- def __init__(self, config: CodSpeedConfig) -> None:
30
+ def __init__(self, config: CodSpeedConfig, mode: MeasurementMode) -> None:
31
+ self.mode = mode
27
32
  self.benchmark_count = 0
28
33
  try:
29
34
  self.instrument_hooks = InstrumentHooks()
@@ -31,7 +36,7 @@ class ValgrindInstrument(Instrument):
31
36
  except RuntimeError as e:
32
37
  if os.environ.get("CODSPEED_ENV") is not None:
33
38
  raise Exception(
34
- "Failed to initialize CPU simulation instrument hooks"
39
+ f"Failed to initialize {self.mode.value} instrument hooks"
35
40
  ) from e
36
41
  self.instrument_hooks = None
37
42
 
@@ -39,7 +44,7 @@ class ValgrindInstrument(Instrument):
39
44
 
40
45
  def get_instrument_config_str_and_warns(self) -> tuple[str, list[str]]:
41
46
  config = (
42
- f"mode: instrumentation, "
47
+ f"mode: {self.mode.value}, "
43
48
  f"callgraph: {'enabled' if SUPPORTS_PERF_TRAMPOLINE else 'not supported'}"
44
49
  )
45
50
  warnings = []
@@ -73,6 +78,9 @@ class ValgrindInstrument(Instrument):
73
78
  # Warmup CPython performance map cache
74
79
  __codspeed_root_frame__()
75
80
 
81
+ self.instrument_hooks.set_feature(FEATURE_DISABLE_CALLGRIND_MARKERS, True)
82
+ self.instrument_hooks.start_benchmark()
83
+
76
84
  # Manually call the library function to avoid an extra stack frame. Also
77
85
  # call the callgrind markers directly to avoid extra overhead.
78
86
  self.instrument_hooks.lib.callgrind_start_instrumentation()
@@ -81,6 +89,7 @@ class ValgrindInstrument(Instrument):
81
89
  finally:
82
90
  # Ensure instrumentation is stopped even if the test failed
83
91
  self.instrument_hooks.lib.callgrind_stop_instrumentation()
92
+ self.instrument_hooks.stop_benchmark()
84
93
  self.instrument_hooks.set_executed_benchmark(uri)
85
94
 
86
95
  def measure_pedantic(
@@ -92,8 +101,8 @@ class ValgrindInstrument(Instrument):
92
101
  ) -> T:
93
102
  if pedantic_options.rounds != 1 or pedantic_options.iterations != 1:
94
103
  warnings.warn(
95
- "Valgrind instrument ignores rounds and iterations settings "
96
- "in pedantic mode"
104
+ f"{self.mode.value.capitalize()} instrument ignores rounds and "
105
+ "iterations settings in pedantic mode"
97
106
  )
98
107
  if not self.instrument_hooks:
99
108
  args, kwargs = pedantic_options.setup_and_get_args_kwargs()
@@ -117,11 +126,18 @@ class ValgrindInstrument(Instrument):
117
126
 
118
127
  # Compute the actual result of the function
119
128
  args, kwargs = pedantic_options.setup_and_get_args_kwargs()
129
+
130
+ self.instrument_hooks.set_feature(FEATURE_DISABLE_CALLGRIND_MARKERS, True)
131
+ self.instrument_hooks.start_benchmark()
132
+
133
+ # Manually call the library function to avoid an extra stack frame. Also
134
+ # call the callgrind markers directly to avoid extra overhead.
120
135
  self.instrument_hooks.lib.callgrind_start_instrumentation()
121
136
  try:
122
137
  out = __codspeed_root_frame__(*args, **kwargs)
123
138
  finally:
124
139
  self.instrument_hooks.lib.callgrind_stop_instrumentation()
140
+ self.instrument_hooks.stop_benchmark()
125
141
  self.instrument_hooks.set_executed_benchmark(uri)
126
142
  if pedantic_options.teardown is not None:
127
143
  pedantic_options.teardown(*args, **kwargs)
@@ -140,5 +156,5 @@ class ValgrindInstrument(Instrument):
140
156
  def get_result_dict(self) -> dict[str, Any]:
141
157
  return {
142
158
  "instrument": {"type": self.instrument},
143
- # bench results will be dumped by valgrind
159
+ # bench results will be dumped by the runner
144
160
  }
@@ -10,6 +10,9 @@ from pytest_codspeed.utils import SUPPORTS_PERF_TRAMPOLINE
10
10
  if TYPE_CHECKING:
11
11
  from .dist_instrument_hooks import InstrumentHooksPointer, LibType
12
12
 
13
+ # Feature flags for instrument hooks
14
+ FEATURE_DISABLE_CALLGRIND_MARKERS = 0
15
+
13
16
 
14
17
  class InstrumentHooks:
15
18
  """Zig library wrapper class providing benchmark measurement functionality."""
@@ -78,5 +81,14 @@ class InstrumentHooks:
78
81
  warnings.warn("Failed to set integration name and version", RuntimeWarning)
79
82
 
80
83
  def is_instrumented(self) -> bool:
81
- """Check if instrumentation is active."""
84
+ """Check if simulation is active."""
82
85
  return self.lib.instrument_hooks_is_instrumented(self.instance)
86
+
87
+ def set_feature(self, feature: int, enabled: bool) -> None:
88
+ """Set a feature flag in the instrument hooks library.
89
+
90
+ Args:
91
+ feature: The feature flag to set
92
+ enabled: Whether to enable or disable the feature
93
+ """
94
+ self.lib.instrument_hooks_set_feature(feature, enabled)
@@ -34,6 +34,8 @@ uint64_t instrument_hooks_current_timestamp(void);
34
34
 
35
35
  void callgrind_start_instrumentation();
36
36
  void callgrind_stop_instrumentation();
37
+
38
+ void instrument_hooks_set_feature(uint64_t feature, bool enabled);
37
39
  """)
38
40
 
39
41
  ffibuilder.set_source(
@@ -29,5 +29,7 @@ class lib:
29
29
  def callgrind_start_instrumentation() -> int: ...
30
30
  @staticmethod
31
31
  def callgrind_stop_instrumentation() -> int: ...
32
+ @staticmethod
33
+ def instrument_hooks_set_feature(feature: int, enabled: bool) -> None: ...
32
34
 
33
35
  LibType = type[lib]