pytest-codspeed 5.0.1__tar.gz → 5.0.2__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.
- {pytest_codspeed-5.0.1/src/pytest_codspeed.egg-info → pytest_codspeed-5.0.2}/PKG-INFO +1 -1
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/pyproject.toml +1 -1
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/__init__.py +2 -2
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/instruments/hooks/__init__.py +48 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/instruments/hooks/instrument_hooks_module.c +19 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2/src/pytest_codspeed.egg-info}/PKG-INFO +1 -1
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/LICENSE +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/README.md +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/setup.cfg +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/setup.py +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/config.py +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/instruments/__init__.py +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/instruments/analysis.py +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/instruments/hooks/instrument-hooks/dist/core.c +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/callgrind.h +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/compat.h +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/core.h +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/valgrind.h +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/instruments/hooks/instrument-hooks/includes/zig.h +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/instruments/hooks/instrument-hooks/scripts/release.py +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/instruments/walltime.py +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/plugin.py +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/py.typed +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/utils.py +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed.egg-info/SOURCES.txt +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed.egg-info/dependency_links.txt +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed.egg-info/entry_points.txt +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed.egg-info/requires.txt +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed.egg-info/top_level.txt +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/tests/test_format_time.py +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/tests/test_pytest_plugin.py +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/tests/test_pytest_plugin_cpu_instrumentation.py +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/tests/test_pytest_plugin_walltime.py +0 -0
- {pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/tests/test_utils.py +0 -0
|
@@ -82,7 +82,7 @@ version = { attr = "pytest_codspeed.__version__" }
|
|
|
82
82
|
|
|
83
83
|
|
|
84
84
|
[tool.bumpver]
|
|
85
|
-
current_version = "5.0.
|
|
85
|
+
current_version = "5.0.2"
|
|
86
86
|
version_pattern = "MAJOR.MINOR.PATCH[-TAG[NUM]]"
|
|
87
87
|
commit_message = "Release v{new_version} 🚀"
|
|
88
88
|
tag_message = "Release v{new_version} 🚀"
|
{pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed/instruments/hooks/__init__.py
RENAMED
|
@@ -50,6 +50,10 @@ class InstrumentHooks:
|
|
|
50
50
|
if SUPPORTS_PERF_TRAMPOLINE and not sys.is_stack_trampoline_active():
|
|
51
51
|
sys.activate_stack_trampoline("perf") # type: ignore
|
|
52
52
|
|
|
53
|
+
# Ignore libpython and python executable frames in callgrind so they
|
|
54
|
+
# don't obfuscate the flamegraph.
|
|
55
|
+
callgrind_skip_python_runtime()
|
|
56
|
+
|
|
53
57
|
def __del__(self):
|
|
54
58
|
# Don't manually deinit - let the capsule destructor handle it
|
|
55
59
|
pass
|
|
@@ -223,3 +227,47 @@ class InstrumentHooks:
|
|
|
223
227
|
self.set_environment_list(section, "config", config_items)
|
|
224
228
|
|
|
225
229
|
self.write_environment()
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def callgrind_add_obj_skip(path: str) -> None:
|
|
233
|
+
"""Tell callgrind to skip the given object file (and its realpath).
|
|
234
|
+
|
|
235
|
+
The actual Valgrind client-request trapdoor lives in the C extension; this
|
|
236
|
+
just resolves the realpath so callgrind's strcmp matches either form.
|
|
237
|
+
"""
|
|
238
|
+
if not path or not os.path.exists(path):
|
|
239
|
+
return
|
|
240
|
+
try:
|
|
241
|
+
from . import dist_instrument_hooks # type: ignore
|
|
242
|
+
except ImportError:
|
|
243
|
+
return
|
|
244
|
+
|
|
245
|
+
dist_instrument_hooks.callgrind_add_obj_skip(path.encode())
|
|
246
|
+
|
|
247
|
+
# The dynamic loader maps the realpath (e.g. libpython3.12.so.1.0), and
|
|
248
|
+
# callgrind stores that in obj_node->name. Skip both so the exact strcmp
|
|
249
|
+
# matches regardless of which path callgrind sees.
|
|
250
|
+
real = os.path.realpath(path)
|
|
251
|
+
if real != path:
|
|
252
|
+
dist_instrument_hooks.callgrind_add_obj_skip(real.encode())
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def callgrind_skip_python_runtime() -> None:
|
|
256
|
+
"""Skip libpython and the python executable from callgrind measurement."""
|
|
257
|
+
ldlibrary = sysconfig.get_config_var("LDLIBRARY")
|
|
258
|
+
libdir = sysconfig.get_config_var("LIBDIR")
|
|
259
|
+
libpython = next(
|
|
260
|
+
(
|
|
261
|
+
p
|
|
262
|
+
for p in (
|
|
263
|
+
os.path.join(libdir, ldlibrary) if ldlibrary and libdir else None,
|
|
264
|
+
os.path.join(sys.prefix, "lib", ldlibrary) if ldlibrary else None,
|
|
265
|
+
)
|
|
266
|
+
if p and os.path.exists(p)
|
|
267
|
+
),
|
|
268
|
+
None,
|
|
269
|
+
)
|
|
270
|
+
if libpython:
|
|
271
|
+
callgrind_add_obj_skip(libpython)
|
|
272
|
+
|
|
273
|
+
callgrind_add_obj_skip(sys.executable)
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
#define PY_SSIZE_T_CLEAN
|
|
2
2
|
#include <Python.h>
|
|
3
3
|
#include "core.h"
|
|
4
|
+
#include "valgrind.h"
|
|
5
|
+
|
|
6
|
+
/* CodSpeed-specific Valgrind client request: tell callgrind to skip an
|
|
7
|
+
* object file by path. Not present in upstream callgrind.h. */
|
|
8
|
+
// TODO(COD-2654): Move this to instrument-hooks and just call it here
|
|
9
|
+
#define VG_USERREQ__ADD_OBJ_SKIP 0x43540006
|
|
4
10
|
|
|
5
11
|
/* Capsule destructor for InstrumentHooks pointer */
|
|
6
12
|
static void instrument_hooks_capsule_destructor(PyObject *capsule) {
|
|
@@ -242,6 +248,17 @@ static PyObject *py_instrument_hooks_write_environment(PyObject *self, PyObject
|
|
|
242
248
|
return PyLong_FromLong(result);
|
|
243
249
|
}
|
|
244
250
|
|
|
251
|
+
/* callgrind_add_obj_skip(path: bytes) -> None
|
|
252
|
+
* Outside Valgrind this expands to a nop, so it's safe on bare metal. */
|
|
253
|
+
static PyObject *py_callgrind_add_obj_skip(PyObject *self, PyObject *args) {
|
|
254
|
+
const char *path;
|
|
255
|
+
if (!PyArg_ParseTuple(args, "y", &path)) {
|
|
256
|
+
return NULL;
|
|
257
|
+
}
|
|
258
|
+
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__ADD_OBJ_SKIP, path, 0, 0, 0, 0);
|
|
259
|
+
Py_RETURN_NONE;
|
|
260
|
+
}
|
|
261
|
+
|
|
245
262
|
/* Method definitions */
|
|
246
263
|
static PyMethodDef InstrumentHooksMethods[] = {
|
|
247
264
|
{"instrument_hooks_init", py_instrument_hooks_init, METH_NOARGS,
|
|
@@ -272,6 +289,8 @@ static PyMethodDef InstrumentHooksMethods[] = {
|
|
|
272
289
|
"Register a list of values under a named section for environment collection."},
|
|
273
290
|
{"instrument_hooks_write_environment", py_instrument_hooks_write_environment, METH_VARARGS,
|
|
274
291
|
"Flush all registered environment sections to disk."},
|
|
292
|
+
{"callgrind_add_obj_skip", py_callgrind_add_obj_skip, METH_VARARGS,
|
|
293
|
+
"Tell callgrind to skip the given object file path."},
|
|
275
294
|
{NULL, NULL, 0, NULL}
|
|
276
295
|
};
|
|
277
296
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/src/pytest_codspeed.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest_codspeed-5.0.1 → pytest_codspeed-5.0.2}/tests/test_pytest_plugin_cpu_instrumentation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|