pytest-codspeed 2.2.0__tar.gz → 3.0.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 (20) hide show
  1. {pytest_codspeed-2.2.0 → pytest_codspeed-3.0.0}/.gitignore +2 -0
  2. {pytest_codspeed-2.2.0 → pytest_codspeed-3.0.0}/PKG-INFO +25 -24
  3. {pytest_codspeed-2.2.0 → pytest_codspeed-3.0.0}/README.md +10 -10
  4. {pytest_codspeed-2.2.0 → pytest_codspeed-3.0.0}/pyproject.toml +24 -13
  5. pytest_codspeed-3.0.0/src/pytest_codspeed/__init__.py +7 -0
  6. pytest_codspeed-3.0.0/src/pytest_codspeed/instruments/__init__.py +60 -0
  7. pytest_codspeed-3.0.0/src/pytest_codspeed/instruments/valgrind/__init__.py +95 -0
  8. {pytest_codspeed-2.2.0/src/pytest_codspeed → pytest_codspeed-3.0.0/src/pytest_codspeed/instruments/valgrind}/_wrapper/.gitignore +1 -0
  9. {pytest_codspeed-2.2.0/src/pytest_codspeed → pytest_codspeed-3.0.0/src/pytest_codspeed/instruments/valgrind}/_wrapper/__init__.py +3 -1
  10. pytest_codspeed-3.0.0/src/pytest_codspeed/instruments/walltime.py +265 -0
  11. pytest_codspeed-3.0.0/src/pytest_codspeed/plugin.py +363 -0
  12. pytest_codspeed-3.0.0/src/pytest_codspeed/py.typed +0 -0
  13. pytest_codspeed-3.0.0/src/pytest_codspeed/utils.py +63 -0
  14. pytest_codspeed-2.2.0/src/pytest_codspeed/__init__.py +0 -5
  15. pytest_codspeed-2.2.0/src/pytest_codspeed/plugin.py +0 -305
  16. pytest_codspeed-2.2.0/src/pytest_codspeed/utils.py +0 -35
  17. {pytest_codspeed-2.2.0 → pytest_codspeed-3.0.0}/LICENSE +0 -0
  18. {pytest_codspeed-2.2.0/src/pytest_codspeed → pytest_codspeed-3.0.0/src/pytest_codspeed/instruments/valgrind}/_wrapper/wrapper.c +0 -0
  19. {pytest_codspeed-2.2.0/src/pytest_codspeed → pytest_codspeed-3.0.0/src/pytest_codspeed/instruments/valgrind}/_wrapper/wrapper.h +0 -0
  20. {pytest_codspeed-2.2.0/src/pytest_codspeed → pytest_codspeed-3.0.0/src/pytest_codspeed/instruments/valgrind}/_wrapper/wrapper.pyi +0 -0
@@ -162,3 +162,5 @@ cython_debug/
162
162
  .venvubuntu
163
163
  .python-version
164
164
  *.o
165
+
166
+ .codspeed
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: pytest-codspeed
3
- Version: 2.2.0
3
+ Version: 3.0.0
4
4
  Summary: Pytest plugin to create CodSpeed benchmarks
5
5
  Project-URL: Homepage, https://codspeed.io/
6
6
  Project-URL: Documentation, https://docs.codspeed.io/
@@ -35,29 +35,30 @@ Classifier: Intended Audience :: Developers
35
35
  Classifier: Intended Audience :: Information Technology
36
36
  Classifier: License :: OSI Approved :: MIT License
37
37
  Classifier: Programming Language :: Python :: 3
38
- Classifier: Programming Language :: Python :: 3.7
39
- Classifier: Programming Language :: Python :: 3.8
40
38
  Classifier: Programming Language :: Python :: 3.9
41
39
  Classifier: Programming Language :: Python :: 3.10
42
40
  Classifier: Programming Language :: Python :: 3.11
43
41
  Classifier: Programming Language :: Python :: 3.12
42
+ Classifier: Programming Language :: Python :: 3.13
44
43
  Classifier: Topic :: Software Development :: Testing
45
44
  Classifier: Topic :: System :: Benchmark
46
45
  Classifier: Topic :: Utilities
47
46
  Classifier: Typing :: Typed
48
- Requires-Python: >=3.7
49
- Requires-Dist: cffi~=1.15.1
50
- Requires-Dist: filelock~=3.12.2
47
+ Requires-Python: >=3.9
48
+ Requires-Dist: cffi>=1.17.1
49
+ Requires-Dist: filelock>=3.12.2
50
+ Requires-Dist: importlib-metadata>=8.5.0; python_version < '3.10'
51
51
  Requires-Dist: pytest>=3.8
52
- Requires-Dist: setuptools~=67.8.0; python_full_version >= '3.12.0b1'
52
+ Requires-Dist: rich>=13.8.1
53
+ Requires-Dist: setuptools; python_full_version >= '3.12.0'
54
+ Provides-Extra: build
55
+ Requires-Dist: semver>=3.0.2; extra == 'build'
53
56
  Provides-Extra: compat
54
- Requires-Dist: pytest-benchmark~=4.0.0; extra == 'compat'
55
- Requires-Dist: pytest-xdist~=2.0.0; extra == 'compat'
57
+ Requires-Dist: pytest-benchmark~=5.0.0; extra == 'compat'
58
+ Requires-Dist: pytest-xdist~=3.6.1; extra == 'compat'
56
59
  Provides-Extra: lint
57
- Requires-Dist: black~=23.3.0; extra == 'lint'
58
- Requires-Dist: isort~=5.12.0; extra == 'lint'
59
- Requires-Dist: mypy~=1.3.0; extra == 'lint'
60
- Requires-Dist: ruff~=0.0.275; extra == 'lint'
60
+ Requires-Dist: mypy~=1.11.2; extra == 'lint'
61
+ Requires-Dist: ruff~=0.6.5; extra == 'lint'
61
62
  Provides-Extra: test
62
63
  Requires-Dist: pytest-cov~=4.0.0; extra == 'test'
63
64
  Requires-Dist: pytest~=7.0; extra == 'test'
@@ -67,11 +68,10 @@ Description-Content-Type: text/markdown
67
68
  <h1>pytest-codspeed</h1>
68
69
 
69
70
  [![CI](https://github.com/CodSpeedHQ/pytest-codspeed/actions/workflows/ci.yml/badge.svg)](https://github.com/CodSpeedHQ/pytest-codspeed/actions/workflows/ci.yml)
70
- <a href="https://pypi.org/project/pytest-codspeed" target="_blank">
71
- <img src="https://img.shields.io/pypi/v/pytest-codspeed?color=%2334D058&label=pypi" alt="Package version">
72
- </a>
73
- <img src="https://img.shields.io/badge/python-3.7%20|%203.8%20|%203.9%20|%203.10%20|%203.11%20|%203.12-informational.svg" alt="python-3.7-3.8-3.9-3.10-3.11-3.12">
71
+ [![PyPi Version](https://img.shields.io/pypi/v/pytest-codspeed?color=%2334D058&label=pypi)](https://pypi.org/project/pytest-codspeed)
72
+ ![Python Version](https://img.shields.io/badge/python-3.9%20|%203.10%20|%203.11%20|%203.12%20|%203.13-informational.svg)
74
73
  [![Discord](https://img.shields.io/badge/chat%20on-discord-7289da.svg)](https://discord.com/invite/MxpaCfKSqF)
74
+ [![CodSpeed Badge](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/CodSpeedHQ/pytest-codspeed)
75
75
 
76
76
  Pytest plugin to create CodSpeed benchmarks
77
77
 
@@ -79,7 +79,7 @@ Pytest plugin to create CodSpeed benchmarks
79
79
 
80
80
  ## Requirements
81
81
 
82
- **Python**: 3.7 and later
82
+ **Python**: 3.9 and later
83
83
 
84
84
  **pytest**: any recent version
85
85
 
@@ -154,7 +154,7 @@ You can use the [CodSpeedHQ/action](https://github.com/CodSpeedHQ/action) to run
154
154
  Example workflow:
155
155
 
156
156
  ```yaml
157
- name: benchmarks
157
+ name: CodSpeed
158
158
 
159
159
  on:
160
160
  push:
@@ -164,16 +164,17 @@ on:
164
164
 
165
165
  jobs:
166
166
  benchmarks:
167
+ name: Run benchmarks
167
168
  runs-on: ubuntu-latest
168
169
  steps:
169
- - uses: actions/checkout@v3
170
- - uses: actions/setup-python@v3
170
+ - uses: actions/checkout@v4
171
+ - uses: actions/setup-python@v5
171
172
  with:
172
- python-version: "3.9"
173
+ python-version: "3.12"
173
174
  - name: Install dependencies
174
175
  run: pip install -r requirements.txt
175
176
  - name: Run benchmarks
176
- uses: CodSpeedHQ/action@v1
177
+ uses: CodSpeedHQ/action@v3
177
178
  with:
178
179
  token: ${{ secrets.CODSPEED_TOKEN }}
179
180
  run: pytest tests/ --codspeed
@@ -2,11 +2,10 @@
2
2
  <h1>pytest-codspeed</h1>
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
- <a href="https://pypi.org/project/pytest-codspeed" target="_blank">
6
- <img src="https://img.shields.io/pypi/v/pytest-codspeed?color=%2334D058&label=pypi" alt="Package version">
7
- </a>
8
- <img src="https://img.shields.io/badge/python-3.7%20|%203.8%20|%203.9%20|%203.10%20|%203.11%20|%203.12-informational.svg" alt="python-3.7-3.8-3.9-3.10-3.11-3.12">
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)
9
7
  [![Discord](https://img.shields.io/badge/chat%20on-discord-7289da.svg)](https://discord.com/invite/MxpaCfKSqF)
8
+ [![CodSpeed Badge](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/CodSpeedHQ/pytest-codspeed)
10
9
 
11
10
  Pytest plugin to create CodSpeed benchmarks
12
11
 
@@ -14,7 +13,7 @@ Pytest plugin to create CodSpeed benchmarks
14
13
 
15
14
  ## Requirements
16
15
 
17
- **Python**: 3.7 and later
16
+ **Python**: 3.9 and later
18
17
 
19
18
  **pytest**: any recent version
20
19
 
@@ -89,7 +88,7 @@ You can use the [CodSpeedHQ/action](https://github.com/CodSpeedHQ/action) to run
89
88
  Example workflow:
90
89
 
91
90
  ```yaml
92
- name: benchmarks
91
+ name: CodSpeed
93
92
 
94
93
  on:
95
94
  push:
@@ -99,16 +98,17 @@ on:
99
98
 
100
99
  jobs:
101
100
  benchmarks:
101
+ name: Run benchmarks
102
102
  runs-on: ubuntu-latest
103
103
  steps:
104
- - uses: actions/checkout@v3
105
- - uses: actions/setup-python@v3
104
+ - uses: actions/checkout@v4
105
+ - uses: actions/setup-python@v5
106
106
  with:
107
- python-version: "3.9"
107
+ python-version: "3.12"
108
108
  - name: Install dependencies
109
109
  run: pip install -r requirements.txt
110
110
  - name: Run benchmarks
111
- uses: CodSpeedHQ/action@v1
111
+ uses: CodSpeedHQ/action@v3
112
112
  with:
113
113
  token: ${{ secrets.CODSPEED_TOKEN }}
114
114
  run: pytest tests/ --codspeed
@@ -13,7 +13,7 @@ dynamic = ["version"]
13
13
  description = "Pytest plugin to create CodSpeed benchmarks"
14
14
  readme = "README.md"
15
15
  license = { file = "LICENSE" }
16
- requires-python = ">=3.7"
16
+ requires-python = ">=3.9"
17
17
  authors = [{ name = "Arthur Pastel", email = "arthur@codspeed.io" }]
18
18
  keywords = ["codspeed", "benchmark", "performance", "pytest"]
19
19
  classifiers = [
@@ -23,29 +23,36 @@ classifiers = [
23
23
  "Intended Audience :: Information Technology",
24
24
  "License :: OSI Approved :: MIT License",
25
25
  "Programming Language :: Python :: 3",
26
- "Programming Language :: Python :: 3.7",
27
- "Programming Language :: Python :: 3.8",
28
26
  "Programming Language :: Python :: 3.9",
29
27
  "Programming Language :: Python :: 3.10",
30
28
  "Programming Language :: Python :: 3.11",
31
29
  "Programming Language :: Python :: 3.12",
30
+ "Programming Language :: Python :: 3.13",
32
31
  "Topic :: Software Development :: Testing",
33
32
  "Topic :: System :: Benchmark",
34
33
  "Topic :: Utilities",
35
34
  "Typing :: Typed",
36
35
  ]
37
36
  dependencies = [
38
- "cffi ~= 1.15.1",
37
+ "cffi >= 1.17.1",
38
+ # cffi doesn't automatically install setuptools with python 3.12+
39
+ # cf https://github.com/python-cffi/cffi/releases/tag/v1.16.0
40
+ "setuptools; python_full_version >= '3.12.0'",
39
41
  "pytest>=3.8",
40
- "filelock ~= 3.12.2",
41
- "setuptools ~= 67.8.0; python_full_version >= '3.12.0b1'", # FIXME: remove when cffi supports directly python 3.12
42
+ "filelock >= 3.12.2",
43
+ "rich>=13.8.1",
44
+ "importlib-metadata>=8.5.0; python_version < '3.10'",
42
45
  ]
43
46
 
44
47
  [project.optional-dependencies]
45
- lint = ["black ~= 23.3.0", "isort ~=5.12.0", "mypy ~= 1.3.0", "ruff ~= 0.0.275"]
46
- compat = ["pytest-benchmark ~= 4.0.0", "pytest-xdist ~= 2.0.0"]
48
+ build = ["semver>=3.0.2"]
49
+ lint = ["mypy ~= 1.11.2", "ruff ~= 0.6.5"]
50
+ compat = [
51
+ "pytest-benchmark ~= 5.0.0",
52
+ "pytest-xdist ~= 3.6.1",
53
+ # "pytest-speed>=0.3.5",
54
+ ]
47
55
  test = ["pytest ~= 7.0", "pytest-cov ~= 4.0.0"]
48
-
49
56
  [project.entry-points]
50
57
  pytest11 = { codspeed = "pytest_codspeed.plugin" }
51
58
 
@@ -57,7 +64,7 @@ features = ["lint", "test", "compat"]
57
64
  features = ["test"]
58
65
 
59
66
  [[tool.hatch.envs.test.matrix]]
60
- python = ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
67
+ python = ["3.9", "3.10", "3.11", "3.12", "3.13"]
61
68
  features = ["compat", "test"]
62
69
 
63
70
  [tool.hatch.version]
@@ -70,8 +77,11 @@ include = ["/src"]
70
77
  python_version = "3.12"
71
78
 
72
79
  [tool.ruff]
73
- line-length = 88
74
- select = ["E", "F", "I", "C"]
80
+ target-version = "py37"
81
+
82
+ [tool.ruff.lint]
83
+ select = ["E", "F", "I", "C", "TCH", "FA", "UP"]
84
+ flake8-type-checking = { exempt-modules = [], strict = true }
75
85
 
76
86
  [tool.isort]
77
87
  line_length = 88
@@ -82,8 +92,9 @@ force_grid_wrap = 0
82
92
  float_to_top = true
83
93
 
84
94
  [tool.pytest.ini_options]
85
- addopts = "--ignore=tests/benchmarks --ignore=tests/examples"
95
+ addopts = "--ignore=tests/benchmarks --ignore=tests/examples --ignore=tests/benchmarks/TheAlgorithms"
86
96
  filterwarnings = ["ignore::DeprecationWarning:pytest_benchmark.utils.*:"]
97
+ pythonpath = ["tests/benchmarks/TheAlgorithms", "./scripts"]
87
98
 
88
99
  [tool.coverage.run]
89
100
  branch = true
@@ -0,0 +1,7 @@
1
+ __version__ = "3.0.0"
2
+ # We also have the semver version since __version__ is not semver compliant
3
+ __semver_version__ = "3.0.0"
4
+
5
+ from .plugin import BenchmarkFixture
6
+
7
+ __all__ = ["BenchmarkFixture", "__version__", "__semver_version__"]
@@ -0,0 +1,60 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABCMeta, abstractmethod
4
+ from enum import Enum
5
+ from typing import TYPE_CHECKING
6
+
7
+ if TYPE_CHECKING:
8
+ from typing import Any, Callable, ClassVar, ParamSpec, TypeVar
9
+
10
+ import pytest
11
+
12
+ from pytest_codspeed.plugin import CodSpeedConfig
13
+
14
+ T = TypeVar("T")
15
+ P = ParamSpec("P")
16
+
17
+
18
+ class Instrument(metaclass=ABCMeta):
19
+ instrument: ClassVar[str]
20
+
21
+ @abstractmethod
22
+ def __init__(self, config: CodSpeedConfig): ...
23
+
24
+ @abstractmethod
25
+ def get_instrument_config_str_and_warns(self) -> tuple[str, list[str]]: ...
26
+
27
+ @abstractmethod
28
+ def measure(
29
+ self,
30
+ name: str,
31
+ uri: str,
32
+ fn: Callable[P, T],
33
+ *args: P.args,
34
+ **kwargs: P.kwargs,
35
+ ) -> T: ...
36
+
37
+ @abstractmethod
38
+ def report(self, session: pytest.Session) -> None: ...
39
+
40
+ @abstractmethod
41
+ def get_result_dict(
42
+ self,
43
+ ) -> dict[str, Any]: ...
44
+
45
+
46
+ class MeasurementMode(str, Enum):
47
+ Instrumentation = "instrumentation"
48
+ WallTime = "walltime"
49
+
50
+
51
+ def get_instrument_from_mode(mode: MeasurementMode) -> type[Instrument]:
52
+ from pytest_codspeed.instruments.valgrind import (
53
+ ValgrindInstrument,
54
+ )
55
+ from pytest_codspeed.instruments.walltime import WallTimeInstrument
56
+
57
+ if mode == MeasurementMode.Instrumentation:
58
+ return ValgrindInstrument
59
+ else:
60
+ return WallTimeInstrument
@@ -0,0 +1,95 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import sys
5
+ from typing import TYPE_CHECKING
6
+
7
+ from pytest_codspeed import __semver_version__
8
+ from pytest_codspeed.instruments import Instrument
9
+ from pytest_codspeed.instruments.valgrind._wrapper import get_lib
10
+
11
+ if TYPE_CHECKING:
12
+ from typing import Any, Callable
13
+
14
+ from pytest import Session
15
+
16
+ from pytest_codspeed.instruments import P, T
17
+ from pytest_codspeed.instruments.valgrind._wrapper import LibType
18
+ from pytest_codspeed.plugin import CodSpeedConfig
19
+
20
+ SUPPORTS_PERF_TRAMPOLINE = sys.version_info >= (3, 12)
21
+
22
+
23
+ class ValgrindInstrument(Instrument):
24
+ instrument = "valgrind"
25
+ lib: LibType | None
26
+
27
+ def __init__(self, config: CodSpeedConfig) -> None:
28
+ self.benchmark_count = 0
29
+ self.should_measure = os.environ.get("CODSPEED_ENV") is not None
30
+ if self.should_measure:
31
+ self.lib = get_lib()
32
+ self.lib.dump_stats_at(
33
+ f"Metadata: pytest-codspeed {__semver_version__}".encode("ascii")
34
+ )
35
+ if SUPPORTS_PERF_TRAMPOLINE:
36
+ sys.activate_stack_trampoline("perf") # type: ignore
37
+ else:
38
+ self.lib = None
39
+
40
+ def get_instrument_config_str_and_warns(self) -> tuple[str, list[str]]:
41
+ config = (
42
+ f"mode: instrumentation, "
43
+ f"callgraph: {'enabled' if SUPPORTS_PERF_TRAMPOLINE else 'not supported'}"
44
+ )
45
+ warnings = []
46
+ if not self.should_measure:
47
+ warnings.append(
48
+ "\033[1m"
49
+ "NOTICE: codspeed is enabled, but no performance measurement"
50
+ " will be made since it's running in an unknown environment."
51
+ "\033[0m"
52
+ )
53
+ return config, warnings
54
+
55
+ def measure(
56
+ self,
57
+ name: str,
58
+ uri: str,
59
+ fn: Callable[P, T],
60
+ *args: P.args,
61
+ **kwargs: P.kwargs,
62
+ ) -> T:
63
+ self.benchmark_count += 1
64
+ if self.lib is None: # Thus should_measure is False
65
+ return fn(*args, **kwargs)
66
+
67
+ def __codspeed_root_frame__() -> T:
68
+ return fn(*args, **kwargs)
69
+
70
+ if SUPPORTS_PERF_TRAMPOLINE:
71
+ # Warmup CPython performance map cache
72
+ __codspeed_root_frame__()
73
+
74
+ self.lib.zero_stats()
75
+ self.lib.start_instrumentation()
76
+ try:
77
+ return __codspeed_root_frame__()
78
+ finally:
79
+ # Ensure instrumentation is stopped even if the test failed
80
+ self.lib.stop_instrumentation()
81
+ self.lib.dump_stats_at(uri.encode("ascii"))
82
+
83
+ def report(self, session: Session) -> None:
84
+ reporter = session.config.pluginmanager.get_plugin("terminalreporter")
85
+ count_suffix = "benchmarked" if self.should_measure else "benchmark tested"
86
+ reporter.write_sep(
87
+ "=",
88
+ f"{self.benchmark_count} {count_suffix}",
89
+ )
90
+
91
+ def get_result_dict(self) -> dict[str, Any]:
92
+ return {
93
+ "instrument": {"type": self.instrument},
94
+ # bench results will be dumped by valgrind
95
+ }
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import os
2
4
  from typing import TYPE_CHECKING
3
5
 
@@ -22,7 +24,7 @@ def _get_ffi():
22
24
  return ffi
23
25
 
24
26
 
25
- def get_lib() -> "LibType":
27
+ def get_lib() -> LibType:
26
28
  try:
27
29
  ffi = _get_ffi()
28
30
  build_lock = FileLock(f"{_wrapper_dir}/build.lock")