Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/pytest_codspeed/instruments/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def __init__(self, config: CodSpeedConfig, mode: MeasurementMode) -> None:
try:
self.instrument_hooks = InstrumentHooks()
self.instrument_hooks.set_integration("pytest-codspeed", __semver_version__)
self.instrument_hooks.collect_and_write_python_environment()
except RuntimeError as e:
if os.environ.get("CODSPEED_ENV") is not None:
raise Exception(
Expand Down
41 changes: 41 additions & 0 deletions src/pytest_codspeed/instruments/hooks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import os
import sys
import sysconfig
import warnings
from typing import TYPE_CHECKING

Expand Down Expand Up @@ -92,3 +93,43 @@ def set_feature(self, feature: int, enabled: bool) -> None:
enabled: Whether to enable or disable the feature
"""
self.lib.instrument_hooks_set_feature(feature, enabled)

def set_environment(self, section_name: str, key: str, value: str) -> None:
"""Register a key-value pair under a named section for environment collection.

Args:
section_name: The section name (e.g. "Python")
key: The key (e.g. "version")
value: The value (e.g. "3.13.12")
"""
ret = self.lib.instrument_hooks_set_environment(
self.instance,
section_name.encode("utf-8"),
key.encode("utf-8"),
value.encode("utf-8"),
)
if ret != 0:
warnings.warn("Failed to set environment data", RuntimeWarning)

def write_environment(self, pid: int | None = None) -> None:
"""Flush all registered environment sections to disk.

Writes to $CODSPEED_PROFILE_FOLDER/environment-<pid>.json.

Args:
pid: Optional process ID (defaults to current process)
"""
if pid is None:
pid = os.getpid()
ret = self.lib.instrument_hooks_write_environment(self.instance, pid)
if ret != 0:
warnings.warn("Failed to write environment data", RuntimeWarning)

def collect_and_write_python_environment(self) -> None:
"""Collect Python toolchain information and write it to disk."""

for key, value in sysconfig.get_config_vars().items():
self.set_environment(
"python", f"{key}", str(value) if value is not None else ""
)
self.write_environment()
6 changes: 6 additions & 0 deletions src/pytest_codspeed/instruments/hooks/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
void callgrind_stop_instrumentation();

void instrument_hooks_set_feature(uint64_t feature, bool enabled);

uint8_t instrument_hooks_set_environment(InstrumentHooks *, const char *section_name,
const char *key, const char *value);
uint8_t instrument_hooks_write_environment(InstrumentHooks *, uint32_t pid);
""")

ffibuilder.set_source(
Expand All @@ -47,6 +51,8 @@
"src/pytest_codspeed/instruments/hooks/instrument-hooks/dist/core.c",
],
include_dirs=[str(includes_dir)],
# IMPORTANT: Keep in sync with instrument-hooks/ci.yml (COMMON_CFLAGS)
extra_compile_args=["-Wno-format-security"],
)

if __name__ == "__main__":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,13 @@ class lib:
def callgrind_stop_instrumentation() -> int: ...
@staticmethod
def instrument_hooks_set_feature(feature: int, enabled: bool) -> None: ...
@staticmethod
def instrument_hooks_set_environment(
hooks: InstrumentHooksPointer, section_name: bytes, key: bytes, value: bytes
) -> int: ...
@staticmethod
def instrument_hooks_write_environment(
hooks: InstrumentHooksPointer, pid: int
) -> int: ...

LibType = type[lib]
1 change: 1 addition & 0 deletions src/pytest_codspeed/instruments/walltime.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ def __init__(self, config: CodSpeedConfig, _mode: MeasurementMode) -> None:
try:
self.instrument_hooks = InstrumentHooks()
self.instrument_hooks.set_integration("pytest-codspeed", __semver_version__)
self.instrument_hooks.collect_and_write_python_environment()
except RuntimeError as e:
if os.environ.get("CODSPEED_ENV") is not None:
warnings.warn(
Expand Down
Loading