pytest-codspeed 4.2.0b0__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.0b0/src/pytest_codspeed.egg-info → pytest_codspeed-4.3.0}/PKG-INFO +10 -9
  2. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/README.md +8 -8
  3. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/pyproject.toml +8 -2
  4. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/__init__.py +2 -2
  5. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/__init__.py +14 -6
  6. pytest_codspeed-4.2.0b0/src/pytest_codspeed/instruments/valgrind.py → pytest_codspeed-4.3.0/src/pytest_codspeed/instruments/analysis.py +31 -10
  7. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/__init__.py +13 -1
  8. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/build.py +2 -0
  9. {pytest_codspeed-4.2.0b0 → 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.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/core.h +1 -0
  13. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/instrument-hooks/scripts/release.py +4 -0
  14. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/walltime.py +36 -3
  15. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/plugin.py +18 -7
  16. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0/src/pytest_codspeed.egg-info}/PKG-INFO +10 -9
  17. {pytest_codspeed-4.2.0b0 → 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.0b0 → pytest_codspeed-4.3.0}/tests/test_pytest_plugin.py +1 -1
  20. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/tests/test_pytest_plugin_cpu_instrumentation.py +7 -9
  21. pytest_codspeed-4.2.0b0/src/pytest_codspeed/instruments/hooks/instrument-hooks/dist/core.c +0 -8638
  22. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/LICENSE +0 -0
  23. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/setup.cfg +0 -0
  24. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/setup.py +0 -0
  25. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/config.py +0 -0
  26. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/callgrind.h +0 -0
  27. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/valgrind.h +0 -0
  28. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/zig.h +0 -0
  29. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/py.typed +0 -0
  30. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed/utils.py +0 -0
  31. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed.egg-info/dependency_links.txt +0 -0
  32. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed.egg-info/entry_points.txt +0 -0
  33. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed.egg-info/requires.txt +0 -0
  34. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/src/pytest_codspeed.egg-info/top_level.txt +0 -0
  35. {pytest_codspeed-4.2.0b0 → pytest_codspeed-4.3.0}/tests/test_pytest_plugin_walltime.py +0 -0
  36. {pytest_codspeed-4.2.0b0 → 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.0b0
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)
@@ -40,6 +40,7 @@ Classifier: Programming Language :: Python :: 3.10
40
40
  Classifier: Programming Language :: Python :: 3.11
41
41
  Classifier: Programming Language :: Python :: 3.12
42
42
  Classifier: Programming Language :: Python :: 3.13
43
+ Classifier: Programming Language :: Python :: 3.14
43
44
  Classifier: Topic :: Software Development :: Testing
44
45
  Classifier: Topic :: System :: Benchmark
45
46
  Classifier: Topic :: Utilities
@@ -59,7 +60,7 @@ Requires-Dist: pytest-xdist~=3.6.1; extra == "compat"
59
60
 
60
61
  [![CI](https://github.com/CodSpeedHQ/pytest-codspeed/actions/workflows/ci.yml/badge.svg)](https://github.com/CodSpeedHQ/pytest-codspeed/actions/workflows/ci.yml)
61
62
  [![PyPi Version](https://img.shields.io/pypi/v/pytest-codspeed?color=%2334D058&label=pypi)](https://pypi.org/project/pytest-codspeed)
62
- ![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)
63
64
  [![Discord](https://img.shields.io/badge/chat%20on-discord-7289da.svg)](https://discord.com/invite/MxpaCfKSqF)
64
65
  [![CodSpeed Badge](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/CodSpeedHQ/pytest-codspeed)
65
66
 
@@ -117,10 +118,10 @@ If you want to run the benchmarks tests locally, you can use the `--codspeed` py
117
118
  ```sh
118
119
  $ pytest tests/ --codspeed
119
120
  ============================= test session starts ====================
120
- platform darwin -- Python 3.13.0, pytest-7.4.4, pluggy-1.5.0
121
- 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)
122
123
  rootdir: /home/user/codspeed-test, configfile: pytest.ini
123
- plugins: codspeed-3.0.0
124
+ plugins: codspeed-4.2.0
124
125
  collected 1 items
125
126
 
126
127
  tests/test_sum_squares.py . [ 100%]
@@ -158,10 +159,10 @@ jobs:
158
159
  name: Run benchmarks
159
160
  runs-on: ubuntu-latest
160
161
  steps:
161
- - uses: actions/checkout@v4
162
- - uses: actions/setup-python@v5
162
+ - uses: actions/checkout@v5
163
+ - uses: actions/setup-python@v6
163
164
  with:
164
- python-version: "3.13"
165
+ python-version: "3.14"
165
166
 
166
167
  - name: Install dependencies
167
168
  run: pip install -r requirements.txt
@@ -169,7 +170,7 @@ jobs:
169
170
  - name: Run benchmarks
170
171
  uses: CodSpeedHQ/action@v4
171
172
  with:
172
- mode: instrumentation # or `walltime`
173
+ mode: simulation # or `walltime`
173
174
  token: ${{ secrets.CODSPEED_TOKEN }}
174
175
  run: pytest tests/ --codspeed
175
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
  ```
@@ -24,6 +24,7 @@ classifiers = [
24
24
  "Programming Language :: Python :: 3.11",
25
25
  "Programming Language :: Python :: 3.12",
26
26
  "Programming Language :: Python :: 3.13",
27
+ "Programming Language :: Python :: 3.14",
27
28
  "Topic :: Software Development :: Testing",
28
29
  "Topic :: System :: Benchmark",
29
30
  "Topic :: Utilities",
@@ -43,13 +44,18 @@ compat = [
43
44
  # "pytest-speed>=0.3.5",
44
45
  ]
45
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
+
46
52
  [tool.uv.sources]
47
53
  pytest-codspeed = { workspace = true }
48
54
 
49
55
  [dependency-groups]
50
56
  dev = [
51
57
  "pytest-codspeed",
52
- "mypy ~= 1.11.2",
58
+ "mypy ~= 1.18.2",
53
59
  "ruff ~= 0.11.12",
54
60
  "pytest ~= 7.0",
55
61
  "pytest-cov ~= 4.0.0",
@@ -71,7 +77,7 @@ version = { attr = "pytest_codspeed.__version__" }
71
77
 
72
78
 
73
79
  [tool.bumpver]
74
- current_version = "4.2.0-beta"
80
+ current_version = "4.3.0"
75
81
  version_pattern = "MAJOR.MINOR.PATCH[-TAG[NUM]]"
76
82
  commit_message = "Release v{new_version} 🚀"
77
83
  tag_message = "Release v{new_version} 🚀"
@@ -1,6 +1,6 @@
1
- __version__ = "4.2.0b0"
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-beta"
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
@@ -1,11 +1,15 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import os
3
4
  import warnings
4
5
  from typing import TYPE_CHECKING
5
6
 
6
7
  from pytest_codspeed import __semver_version__
7
8
  from pytest_codspeed.instruments import Instrument
8
- from pytest_codspeed.instruments.hooks import InstrumentHooks
9
+ from pytest_codspeed.instruments.hooks import (
10
+ FEATURE_DISABLE_CALLGRIND_MARKERS,
11
+ InstrumentHooks,
12
+ )
9
13
  from pytest_codspeed.utils import SUPPORTS_PERF_TRAMPOLINE
10
14
 
11
15
  if TYPE_CHECKING:
@@ -14,27 +18,33 @@ if TYPE_CHECKING:
14
18
  from pytest import Session
15
19
 
16
20
  from pytest_codspeed.config import PedanticOptions
17
- from pytest_codspeed.instruments import P, T
21
+ from pytest_codspeed.instruments import MeasurementMode, P, T
18
22
  from pytest_codspeed.plugin import BenchmarkMarkerOptions, CodSpeedConfig
19
23
 
20
24
 
21
- class ValgrindInstrument(Instrument):
22
- instrument = "valgrind"
25
+ class AnalysisInstrument(Instrument):
26
+ instrument = "analysis"
23
27
  instrument_hooks: InstrumentHooks | None
28
+ mode: MeasurementMode
24
29
 
25
- def __init__(self, config: CodSpeedConfig) -> None:
30
+ def __init__(self, config: CodSpeedConfig, mode: MeasurementMode) -> None:
31
+ self.mode = mode
26
32
  self.benchmark_count = 0
27
33
  try:
28
34
  self.instrument_hooks = InstrumentHooks()
29
35
  self.instrument_hooks.set_integration("pytest-codspeed", __semver_version__)
30
- except RuntimeError:
36
+ except RuntimeError as e:
37
+ if os.environ.get("CODSPEED_ENV") is not None:
38
+ raise Exception(
39
+ f"Failed to initialize {self.mode.value} instrument hooks"
40
+ ) from e
31
41
  self.instrument_hooks = None
32
42
 
33
43
  self.should_measure = self.instrument_hooks is not None
34
44
 
35
45
  def get_instrument_config_str_and_warns(self) -> tuple[str, list[str]]:
36
46
  config = (
37
- f"mode: instrumentation, "
47
+ f"mode: {self.mode.value}, "
38
48
  f"callgraph: {'enabled' if SUPPORTS_PERF_TRAMPOLINE else 'not supported'}"
39
49
  )
40
50
  warnings = []
@@ -68,6 +78,9 @@ class ValgrindInstrument(Instrument):
68
78
  # Warmup CPython performance map cache
69
79
  __codspeed_root_frame__()
70
80
 
81
+ self.instrument_hooks.set_feature(FEATURE_DISABLE_CALLGRIND_MARKERS, True)
82
+ self.instrument_hooks.start_benchmark()
83
+
71
84
  # Manually call the library function to avoid an extra stack frame. Also
72
85
  # call the callgrind markers directly to avoid extra overhead.
73
86
  self.instrument_hooks.lib.callgrind_start_instrumentation()
@@ -76,6 +89,7 @@ class ValgrindInstrument(Instrument):
76
89
  finally:
77
90
  # Ensure instrumentation is stopped even if the test failed
78
91
  self.instrument_hooks.lib.callgrind_stop_instrumentation()
92
+ self.instrument_hooks.stop_benchmark()
79
93
  self.instrument_hooks.set_executed_benchmark(uri)
80
94
 
81
95
  def measure_pedantic(
@@ -87,8 +101,8 @@ class ValgrindInstrument(Instrument):
87
101
  ) -> T:
88
102
  if pedantic_options.rounds != 1 or pedantic_options.iterations != 1:
89
103
  warnings.warn(
90
- "Valgrind instrument ignores rounds and iterations settings "
91
- "in pedantic mode"
104
+ f"{self.mode.value.capitalize()} instrument ignores rounds and "
105
+ "iterations settings in pedantic mode"
92
106
  )
93
107
  if not self.instrument_hooks:
94
108
  args, kwargs = pedantic_options.setup_and_get_args_kwargs()
@@ -112,11 +126,18 @@ class ValgrindInstrument(Instrument):
112
126
 
113
127
  # Compute the actual result of the function
114
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.
115
135
  self.instrument_hooks.lib.callgrind_start_instrumentation()
116
136
  try:
117
137
  out = __codspeed_root_frame__(*args, **kwargs)
118
138
  finally:
119
139
  self.instrument_hooks.lib.callgrind_stop_instrumentation()
140
+ self.instrument_hooks.stop_benchmark()
120
141
  self.instrument_hooks.set_executed_benchmark(uri)
121
142
  if pedantic_options.teardown is not None:
122
143
  pedantic_options.teardown(*args, **kwargs)
@@ -135,5 +156,5 @@ class ValgrindInstrument(Instrument):
135
156
  def get_result_dict(self) -> dict[str, Any]:
136
157
  return {
137
158
  "instrument": {"type": self.instrument},
138
- # bench results will be dumped by valgrind
159
+ # bench results will be dumped by the runner
139
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]