diff --git a/pyproject.toml b/pyproject.toml index 0ab2879..62d9fa0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,6 @@ classifiers = [ "Typing :: Typed", ] dependencies = [ - "cffi >= 1.17.1", "pytest>=3.8", "rich>=13.8.1", "importlib-metadata>=8.5.0; python_version < '3.10'", @@ -64,12 +63,17 @@ dev = [ pytest11 = { codspeed = "pytest_codspeed.plugin" } [build-system] -requires = ["setuptools >= 61", "cffi >= 1.17.1"] +requires = ["setuptools >= 61"] build-backend = "setuptools.build_meta" [tool.setuptools] license-files = [] # Workaround of https://github.com/astral-sh/uv/issues/9513 +[tool.setuptools.package-data] +pytest_codspeed = [ + "instruments/hooks/instrument-hooks/includes/*.h", +] + [tool.setuptools.dynamic] version = { attr = "pytest_codspeed.__version__" } diff --git a/setup.py b/setup.py index e0657bb..84eff3d 100644 --- a/setup.py +++ b/setup.py @@ -1,17 +1,7 @@ -import importlib.util import os import platform -from pathlib import Path -from setuptools import setup - -build_path = Path(__file__).parent / "src/pytest_codspeed/instruments/hooks/build.py" - -spec = importlib.util.spec_from_file_location("build", build_path) -assert spec is not None, "The spec should be initialized" -build = importlib.util.module_from_spec(spec) -assert spec.loader is not None, "The loader should be initialized" -spec.loader.exec_module(build) +from setuptools import Extension, setup system = platform.system() current_arch = platform.machine() @@ -39,8 +29,16 @@ "The extension is required but the current platform is not supported" ) -ffi_extension = build.ffibuilder.distutils_extension() -ffi_extension.optional = not IS_EXTENSION_REQUIRED +# Build native C extension +native_extension = Extension( + "pytest_codspeed.instruments.hooks.dist_instrument_hooks", + sources=[ + "src/pytest_codspeed/instruments/hooks/instrument_hooks_module.c", + "src/pytest_codspeed/instruments/hooks/instrument-hooks/dist/core.c", + ], + include_dirs=["src/pytest_codspeed/instruments/hooks/instrument-hooks/includes"], + optional=not IS_EXTENSION_REQUIRED, +) print( "CodSpeed native extension is " @@ -48,13 +46,9 @@ ) setup( - package_data={ - "pytest_codspeed": [ - "instruments/hooks/instrument-hooks/includes/*.h", - "instruments/hooks/instrument-hooks/dist/*.c", - ] - }, ext_modules=( - [ffi_extension] if IS_EXTENSION_BUILDABLE and not SKIP_EXTENSION_BUILD else [] + [native_extension] + if IS_EXTENSION_BUILDABLE and not SKIP_EXTENSION_BUILD + else [] ), ) diff --git a/src/pytest_codspeed/instruments/hooks/__init__.py b/src/pytest_codspeed/instruments/hooks/__init__.py index 19aea91..7a1cbcf 100644 --- a/src/pytest_codspeed/instruments/hooks/__init__.py +++ b/src/pytest_codspeed/instruments/hooks/__init__.py @@ -5,17 +5,17 @@ import warnings from typing import TYPE_CHECKING -from pytest_codspeed.utils import SUPPORTS_PERF_TRAMPOLINE - if TYPE_CHECKING: - from .dist_instrument_hooks import InstrumentHooksPointer, LibType + from typing import Any + +from pytest_codspeed.utils import SUPPORTS_PERF_TRAMPOLINE class InstrumentHooks: - """Zig library wrapper class providing benchmark measurement functionality.""" + """Native library wrapper class providing benchmark measurement functionality.""" - lib: LibType - instance: InstrumentHooksPointer + _module: Any + _instance: Any def __init__(self) -> None: if os.environ.get("CODSPEED_ENV") is None: @@ -25,31 +25,31 @@ def __init__(self) -> None: ) try: - from .dist_instrument_hooks import lib # type: ignore + from . import dist_instrument_hooks # type: ignore except ImportError as e: raise RuntimeError(f"Failed to load instrument hooks library: {e}") from e - self.lib = lib + self._module = dist_instrument_hooks - self.instance = self.lib.instrument_hooks_init() - if self.instance == 0: + self._instance = self._module.instrument_hooks_init() + if self._instance is None: raise RuntimeError("Failed to initialize CodSpeed instrumentation library.") if SUPPORTS_PERF_TRAMPOLINE: sys.activate_stack_trampoline("perf") # type: ignore def __del__(self): - if hasattr(self, "lib") and hasattr(self, "instance"): - self.lib.instrument_hooks_deinit(self.instance) + # Don't manually deinit - let the capsule destructor handle it + pass def start_benchmark(self) -> None: """Start a new benchmark measurement.""" - ret = self.lib.instrument_hooks_start_benchmark(self.instance) + ret = self._module.instrument_hooks_start_benchmark(self._instance) if ret != 0: warnings.warn("Failed to start benchmark measurement", RuntimeWarning) def stop_benchmark(self) -> None: """Stop the current benchmark measurement.""" - ret = self.lib.instrument_hooks_stop_benchmark(self.instance) + ret = self._module.instrument_hooks_stop_benchmark(self._instance) if ret != 0: warnings.warn("Failed to stop benchmark measurement", RuntimeWarning) @@ -63,20 +63,28 @@ def set_executed_benchmark(self, uri: str, pid: int | None = None) -> None: if pid is None: pid = os.getpid() - ret = self.lib.instrument_hooks_set_executed_benchmark( - self.instance, pid, uri.encode("ascii") + ret = self._module.instrument_hooks_set_executed_benchmark( + self._instance, pid, uri.encode("ascii") ) if ret != 0: warnings.warn("Failed to set executed benchmark", RuntimeWarning) def set_integration(self, name: str, version: str) -> None: """Set the integration name and version.""" - ret = self.lib.instrument_hooks_set_integration( - self.instance, name.encode("ascii"), version.encode("ascii") + ret = self._module.instrument_hooks_set_integration( + self._instance, name.encode("ascii"), version.encode("ascii") ) if ret != 0: warnings.warn("Failed to set integration name and version", RuntimeWarning) def is_instrumented(self) -> bool: """Check if instrumentation is active.""" - return self.lib.instrument_hooks_is_instrumented(self.instance) + return self._module.instrument_hooks_is_instrumented(self._instance) + + def callgrind_start_instrumentation(self) -> None: + """Start callgrind instrumentation.""" + self._module.callgrind_start_instrumentation() + + def callgrind_stop_instrumentation(self) -> None: + """Stop callgrind instrumentation.""" + self._module.callgrind_stop_instrumentation() diff --git a/src/pytest_codspeed/instruments/hooks/build.py b/src/pytest_codspeed/instruments/hooks/build.py deleted file mode 100644 index 992ee01..0000000 --- a/src/pytest_codspeed/instruments/hooks/build.py +++ /dev/null @@ -1,51 +0,0 @@ -from pathlib import Path - -from cffi import FFI # type: ignore - -ffibuilder = FFI() - -includes_dir = Path(__file__).parent.joinpath("instrument-hooks/includes") -header_text = (includes_dir / "core.h").read_text() - - -# Manually copied from `instrument-hooks/includes/core.h` to avoid parsing issues -ffibuilder.cdef(""" -typedef uint64_t *InstrumentHooks; - -InstrumentHooks *instrument_hooks_init(void); -void instrument_hooks_deinit(InstrumentHooks *); - -bool instrument_hooks_is_instrumented(InstrumentHooks *); -uint8_t instrument_hooks_start_benchmark(InstrumentHooks *); -uint8_t instrument_hooks_stop_benchmark(InstrumentHooks *); -uint8_t instrument_hooks_set_executed_benchmark(InstrumentHooks *, int32_t pid, - const char *uri); -uint8_t instrument_hooks_set_integration(InstrumentHooks *, const char *name, - const char *version); - -#define MARKER_TYPE_SAMPLE_START 0 -#define MARKER_TYPE_SAMPLE_END 1 -#define MARKER_TYPE_BENCHMARK_START 2 -#define MARKER_TYPE_BENCHMARK_END 3 - -uint8_t instrument_hooks_add_marker(InstrumentHooks *, uint32_t pid, - uint8_t marker_type, uint64_t timestamp); -uint64_t instrument_hooks_current_timestamp(void); - -void callgrind_start_instrumentation(); -void callgrind_stop_instrumentation(); -""") - -ffibuilder.set_source( - "pytest_codspeed.instruments.hooks.dist_instrument_hooks", - """ - #include "core.h" - """, - sources=[ - "src/pytest_codspeed/instruments/hooks/instrument-hooks/dist/core.c", - ], - include_dirs=[str(includes_dir)], -) - -if __name__ == "__main__": - ffibuilder.compile(verbose=True) diff --git a/src/pytest_codspeed/instruments/hooks/instrument_hooks_module.c b/src/pytest_codspeed/instruments/hooks/instrument_hooks_module.c new file mode 100644 index 0000000..dc94b21 --- /dev/null +++ b/src/pytest_codspeed/instruments/hooks/instrument_hooks_module.c @@ -0,0 +1,213 @@ +#define PY_SSIZE_T_CLEAN +#include +#include "core.h" + +/* Capsule destructor for InstrumentHooks pointer */ +static void instrument_hooks_capsule_destructor(PyObject *capsule) { + InstrumentHooks *hooks = (InstrumentHooks *)PyCapsule_GetPointer(capsule, "instrument_hooks"); + if (hooks) { + instrument_hooks_deinit(hooks); + } +} + +/* instrument_hooks_init() -> capsule */ +static PyObject *py_instrument_hooks_init(PyObject *self, PyObject *args) { + InstrumentHooks *hooks = instrument_hooks_init(); + if (!hooks) { + PyErr_SetString(PyExc_RuntimeError, "Failed to initialize instrument hooks"); + return NULL; + } + return PyCapsule_New(hooks, "instrument_hooks", instrument_hooks_capsule_destructor); +} + +/* instrument_hooks_deinit(capsule) -> None */ +static PyObject *py_instrument_hooks_deinit(PyObject *self, PyObject *args) { + PyObject *capsule; + if (!PyArg_ParseTuple(args, "O", &capsule)) { + return NULL; + } + + InstrumentHooks *hooks = (InstrumentHooks *)PyCapsule_GetPointer(capsule, "instrument_hooks"); + if (!hooks) { + return NULL; + } + + instrument_hooks_deinit(hooks); + Py_RETURN_NONE; +} + +/* instrument_hooks_is_instrumented(capsule) -> bool */ +static PyObject *py_instrument_hooks_is_instrumented(PyObject *self, PyObject *args) { + PyObject *capsule; + if (!PyArg_ParseTuple(args, "O", &capsule)) { + return NULL; + } + + InstrumentHooks *hooks = (InstrumentHooks *)PyCapsule_GetPointer(capsule, "instrument_hooks"); + if (!hooks) { + return NULL; + } + + bool result = instrument_hooks_is_instrumented(hooks); + return PyBool_FromLong(result); +} + +/* instrument_hooks_start_benchmark(capsule) -> int */ +static PyObject *py_instrument_hooks_start_benchmark(PyObject *self, PyObject *args) { + PyObject *capsule; + if (!PyArg_ParseTuple(args, "O", &capsule)) { + return NULL; + } + + InstrumentHooks *hooks = (InstrumentHooks *)PyCapsule_GetPointer(capsule, "instrument_hooks"); + if (!hooks) { + return NULL; + } + + uint8_t result = instrument_hooks_start_benchmark(hooks); + return PyLong_FromLong(result); +} + +/* instrument_hooks_stop_benchmark(capsule) -> int */ +static PyObject *py_instrument_hooks_stop_benchmark(PyObject *self, PyObject *args) { + PyObject *capsule; + if (!PyArg_ParseTuple(args, "O", &capsule)) { + return NULL; + } + + InstrumentHooks *hooks = (InstrumentHooks *)PyCapsule_GetPointer(capsule, "instrument_hooks"); + if (!hooks) { + return NULL; + } + + uint8_t result = instrument_hooks_stop_benchmark(hooks); + return PyLong_FromLong(result); +} + +/* instrument_hooks_set_executed_benchmark(capsule, pid, uri) -> int */ +static PyObject *py_instrument_hooks_set_executed_benchmark(PyObject *self, PyObject *args) { + PyObject *capsule; + int32_t pid; + const char *uri; + + if (!PyArg_ParseTuple(args, "Oiy", &capsule, &pid, &uri)) { + return NULL; + } + + InstrumentHooks *hooks = (InstrumentHooks *)PyCapsule_GetPointer(capsule, "instrument_hooks"); + if (!hooks) { + return NULL; + } + + uint8_t result = instrument_hooks_set_executed_benchmark(hooks, pid, uri); + return PyLong_FromLong(result); +} + +/* instrument_hooks_set_integration(capsule, name, version) -> int */ +static PyObject *py_instrument_hooks_set_integration(PyObject *self, PyObject *args) { + PyObject *capsule; + const char *name; + const char *version; + + if (!PyArg_ParseTuple(args, "Oyy", &capsule, &name, &version)) { + return NULL; + } + + InstrumentHooks *hooks = (InstrumentHooks *)PyCapsule_GetPointer(capsule, "instrument_hooks"); + if (!hooks) { + return NULL; + } + + uint8_t result = instrument_hooks_set_integration(hooks, name, version); + return PyLong_FromLong(result); +} + +/* instrument_hooks_add_marker(capsule, pid, marker_type, timestamp) -> int */ +static PyObject *py_instrument_hooks_add_marker(PyObject *self, PyObject *args) { + PyObject *capsule; + uint32_t pid; + uint8_t marker_type; + uint64_t timestamp; + + if (!PyArg_ParseTuple(args, "OIIK", &capsule, &pid, &marker_type, ×tamp)) { + return NULL; + } + + InstrumentHooks *hooks = (InstrumentHooks *)PyCapsule_GetPointer(capsule, "instrument_hooks"); + if (!hooks) { + return NULL; + } + + uint8_t result = instrument_hooks_add_marker(hooks, pid, marker_type, timestamp); + return PyLong_FromLong(result); +} + +/* instrument_hooks_current_timestamp() -> int */ +static PyObject *py_instrument_hooks_current_timestamp(PyObject *self, PyObject *args) { + uint64_t result = instrument_hooks_current_timestamp(); + return PyLong_FromUnsignedLongLong(result); +} + +/* callgrind_start_instrumentation() -> None */ +static PyObject *py_callgrind_start_instrumentation(PyObject *self, PyObject *args) { + callgrind_start_instrumentation(); + Py_RETURN_NONE; +} + +/* callgrind_stop_instrumentation() -> None */ +static PyObject *py_callgrind_stop_instrumentation(PyObject *self, PyObject *args) { + callgrind_stop_instrumentation(); + Py_RETURN_NONE; +} + +/* Method definitions */ +static PyMethodDef InstrumentHooksMethods[] = { + {"instrument_hooks_init", py_instrument_hooks_init, METH_NOARGS, + "Initialize instrument hooks and return a handle."}, + {"instrument_hooks_deinit", py_instrument_hooks_deinit, METH_VARARGS, + "Deinitialize instrument hooks."}, + {"instrument_hooks_is_instrumented", py_instrument_hooks_is_instrumented, METH_VARARGS, + "Check if instrumentation is active."}, + {"instrument_hooks_start_benchmark", py_instrument_hooks_start_benchmark, METH_VARARGS, + "Start a benchmark measurement."}, + {"instrument_hooks_stop_benchmark", py_instrument_hooks_stop_benchmark, METH_VARARGS, + "Stop a benchmark measurement."}, + {"instrument_hooks_set_executed_benchmark", py_instrument_hooks_set_executed_benchmark, METH_VARARGS, + "Set the executed benchmark URI and PID."}, + {"instrument_hooks_set_integration", py_instrument_hooks_set_integration, METH_VARARGS, + "Set the integration name and version."}, + {"instrument_hooks_add_marker", py_instrument_hooks_add_marker, METH_VARARGS, + "Add a marker to the instrumentation."}, + {"instrument_hooks_current_timestamp", py_instrument_hooks_current_timestamp, METH_NOARGS, + "Get the current timestamp."}, + {"callgrind_start_instrumentation", py_callgrind_start_instrumentation, METH_NOARGS, + "Start callgrind instrumentation."}, + {"callgrind_stop_instrumentation", py_callgrind_stop_instrumentation, METH_NOARGS, + "Stop callgrind instrumentation."}, + {NULL, NULL, 0, NULL} +}; + +/* Module definition */ +static struct PyModuleDef instrument_hooks_module = { + PyModuleDef_HEAD_INIT, + "dist_instrument_hooks", + "Native Python bindings for instrument hooks library", + -1, + InstrumentHooksMethods +}; + +/* Module initialization */ +PyMODINIT_FUNC PyInit_dist_instrument_hooks(void) { + PyObject *module = PyModule_Create(&instrument_hooks_module); + if (module == NULL) { + return NULL; + } + + /* Add constants */ + PyModule_AddIntConstant(module, "MARKER_TYPE_SAMPLE_START", MARKER_TYPE_SAMPLE_START); + PyModule_AddIntConstant(module, "MARKER_TYPE_SAMPLE_END", MARKER_TYPE_SAMPLE_END); + PyModule_AddIntConstant(module, "MARKER_TYPE_BENCHMARK_START", MARKER_TYPE_BENCHMARK_START); + PyModule_AddIntConstant(module, "MARKER_TYPE_BENCHMARK_END", MARKER_TYPE_BENCHMARK_END); + + return module; +} diff --git a/src/pytest_codspeed/instruments/valgrind.py b/src/pytest_codspeed/instruments/valgrind.py index f604d1f..3251b59 100644 --- a/src/pytest_codspeed/instruments/valgrind.py +++ b/src/pytest_codspeed/instruments/valgrind.py @@ -75,12 +75,12 @@ def __codspeed_root_frame__() -> T: # Manually call the library function to avoid an extra stack frame. Also # call the callgrind markers directly to avoid extra overhead. - self.instrument_hooks.lib.callgrind_start_instrumentation() + self.instrument_hooks.callgrind_start_instrumentation() try: return __codspeed_root_frame__() finally: # Ensure instrumentation is stopped even if the test failed - self.instrument_hooks.lib.callgrind_stop_instrumentation() + self.instrument_hooks.callgrind_stop_instrumentation() self.instrument_hooks.set_executed_benchmark(uri) def measure_pedantic( @@ -117,11 +117,11 @@ def __codspeed_root_frame__(*args, **kwargs) -> T: # Compute the actual result of the function args, kwargs = pedantic_options.setup_and_get_args_kwargs() - self.instrument_hooks.lib.callgrind_start_instrumentation() + self.instrument_hooks.callgrind_start_instrumentation() try: out = __codspeed_root_frame__(*args, **kwargs) finally: - self.instrument_hooks.lib.callgrind_stop_instrumentation() + self.instrument_hooks.callgrind_stop_instrumentation() self.instrument_hooks.set_executed_benchmark(uri) if pedantic_options.teardown is not None: pedantic_options.teardown(*args, **kwargs) diff --git a/uv.lock b/uv.lock index 32198a5..24a7bc8 100644 --- a/uv.lock +++ b/uv.lock @@ -1,76 +1,7 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.9" -[[package]] -name = "cffi" -version = "1.17.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pycparser" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/90/07/f44ca684db4e4f08a3fdc6eeb9a0d15dc6883efc7b8c90357fdbf74e186c/cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", size = 182191, upload-time = "2024-09-04T20:43:30.027Z" }, - { url = "https://files.pythonhosted.org/packages/08/fd/cc2fedbd887223f9f5d170c96e57cbf655df9831a6546c1727ae13fa977a/cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", size = 178592, upload-time = "2024-09-04T20:43:32.108Z" }, - { url = "https://files.pythonhosted.org/packages/de/cc/4635c320081c78d6ffc2cab0a76025b691a91204f4aa317d568ff9280a2d/cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", size = 426024, upload-time = "2024-09-04T20:43:34.186Z" }, - { url = "https://files.pythonhosted.org/packages/b6/7b/3b2b250f3aab91abe5f8a51ada1b717935fdaec53f790ad4100fe2ec64d1/cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", size = 448188, upload-time = "2024-09-04T20:43:36.286Z" }, - { url = "https://files.pythonhosted.org/packages/d3/48/1b9283ebbf0ec065148d8de05d647a986c5f22586b18120020452fff8f5d/cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", size = 455571, upload-time = "2024-09-04T20:43:38.586Z" }, - { url = "https://files.pythonhosted.org/packages/40/87/3b8452525437b40f39ca7ff70276679772ee7e8b394934ff60e63b7b090c/cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", size = 436687, upload-time = "2024-09-04T20:43:40.084Z" }, - { url = "https://files.pythonhosted.org/packages/8d/fb/4da72871d177d63649ac449aec2e8a29efe0274035880c7af59101ca2232/cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", size = 446211, upload-time = "2024-09-04T20:43:41.526Z" }, - { url = "https://files.pythonhosted.org/packages/ab/a0/62f00bcb411332106c02b663b26f3545a9ef136f80d5df746c05878f8c4b/cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", size = 461325, upload-time = "2024-09-04T20:43:43.117Z" }, - { url = "https://files.pythonhosted.org/packages/36/83/76127035ed2e7e27b0787604d99da630ac3123bfb02d8e80c633f218a11d/cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", size = 438784, upload-time = "2024-09-04T20:43:45.256Z" }, - { url = "https://files.pythonhosted.org/packages/21/81/a6cd025db2f08ac88b901b745c163d884641909641f9b826e8cb87645942/cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", size = 461564, upload-time = "2024-09-04T20:43:46.779Z" }, - { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804, upload-time = "2024-09-04T20:43:48.186Z" }, - { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299, upload-time = "2024-09-04T20:43:49.812Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264, upload-time = "2024-09-04T20:43:51.124Z" }, - { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651, upload-time = "2024-09-04T20:43:52.872Z" }, - { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259, upload-time = "2024-09-04T20:43:56.123Z" }, - { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200, upload-time = "2024-09-04T20:43:57.891Z" }, - { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235, upload-time = "2024-09-04T20:44:00.18Z" }, - { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721, upload-time = "2024-09-04T20:44:01.585Z" }, - { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242, upload-time = "2024-09-04T20:44:03.467Z" }, - { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999, upload-time = "2024-09-04T20:44:05.023Z" }, - { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242, upload-time = "2024-09-04T20:44:06.444Z" }, - { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604, upload-time = "2024-09-04T20:44:08.206Z" }, - { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727, upload-time = "2024-09-04T20:44:09.481Z" }, - { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400, upload-time = "2024-09-04T20:44:10.873Z" }, - { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178, upload-time = "2024-09-04T20:44:12.232Z" }, - { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840, upload-time = "2024-09-04T20:44:13.739Z" }, - { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803, upload-time = "2024-09-04T20:44:15.231Z" }, - { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload-time = "2024-09-04T20:44:17.188Z" }, - { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload-time = "2024-09-04T20:44:18.688Z" }, - { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload-time = "2024-09-04T20:44:20.248Z" }, - { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload-time = "2024-09-04T20:44:21.673Z" }, - { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload-time = "2024-09-04T20:44:23.245Z" }, - { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload-time = "2024-09-04T20:44:24.757Z" }, - { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload-time = "2024-09-04T20:44:26.208Z" }, - { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" }, - { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989, upload-time = "2024-09-04T20:44:28.956Z" }, - { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802, upload-time = "2024-09-04T20:44:30.289Z" }, - { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload-time = "2024-09-04T20:44:32.01Z" }, - { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893, upload-time = "2024-09-04T20:44:33.606Z" }, - { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810, upload-time = "2024-09-04T20:44:35.191Z" }, - { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200, upload-time = "2024-09-04T20:44:36.743Z" }, - { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447, upload-time = "2024-09-04T20:44:38.492Z" }, - { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358, upload-time = "2024-09-04T20:44:40.046Z" }, - { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469, upload-time = "2024-09-04T20:44:41.616Z" }, - { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475, upload-time = "2024-09-04T20:44:43.733Z" }, - { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload-time = "2024-09-04T20:44:45.309Z" }, - { url = "https://files.pythonhosted.org/packages/b9/ea/8bb50596b8ffbc49ddd7a1ad305035daa770202a6b782fc164647c2673ad/cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16", size = 182220, upload-time = "2024-09-04T20:45:01.577Z" }, - { url = "https://files.pythonhosted.org/packages/ae/11/e77c8cd24f58285a82c23af484cf5b124a376b32644e445960d1a4654c3a/cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36", size = 178605, upload-time = "2024-09-04T20:45:03.837Z" }, - { url = "https://files.pythonhosted.org/packages/ed/65/25a8dc32c53bf5b7b6c2686b42ae2ad58743f7ff644844af7cdb29b49361/cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8", size = 424910, upload-time = "2024-09-04T20:45:05.315Z" }, - { url = "https://files.pythonhosted.org/packages/42/7a/9d086fab7c66bd7c4d0f27c57a1b6b068ced810afc498cc8c49e0088661c/cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576", size = 447200, upload-time = "2024-09-04T20:45:06.903Z" }, - { url = "https://files.pythonhosted.org/packages/da/63/1785ced118ce92a993b0ec9e0d0ac8dc3e5dbfbcaa81135be56c69cabbb6/cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", size = 454565, upload-time = "2024-09-04T20:45:08.975Z" }, - { url = "https://files.pythonhosted.org/packages/74/06/90b8a44abf3556599cdec107f7290277ae8901a58f75e6fe8f970cd72418/cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0", size = 435635, upload-time = "2024-09-04T20:45:10.64Z" }, - { url = "https://files.pythonhosted.org/packages/bd/62/a1f468e5708a70b1d86ead5bab5520861d9c7eacce4a885ded9faa7729c3/cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3", size = 445218, upload-time = "2024-09-04T20:45:12.366Z" }, - { url = "https://files.pythonhosted.org/packages/5b/95/b34462f3ccb09c2594aa782d90a90b045de4ff1f70148ee79c69d37a0a5a/cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595", size = 460486, upload-time = "2024-09-04T20:45:13.935Z" }, - { url = "https://files.pythonhosted.org/packages/fc/fc/a1e4bebd8d680febd29cf6c8a40067182b64f00c7d105f8f26b5bc54317b/cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a", size = 437911, upload-time = "2024-09-04T20:45:15.696Z" }, - { url = "https://files.pythonhosted.org/packages/e6/c3/21cab7a6154b6a5ea330ae80de386e7665254835b9e98ecc1340b3a7de9a/cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e", size = 460632, upload-time = "2024-09-04T20:45:17.284Z" }, - { url = "https://files.pythonhosted.org/packages/cb/b5/fd9f8b5a84010ca169ee49f4e4ad6f8c05f4e3545b72ee041dbbcb159882/cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", size = 171820, upload-time = "2024-09-04T20:45:18.762Z" }, - { url = "https://files.pythonhosted.org/packages/8c/52/b08750ce0bce45c143e1b5d7357ee8c55341b52bdef4b0f081af1eb248c2/cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", size = 181290, upload-time = "2024-09-04T20:45:20.226Z" }, -] - [[package]] name = "colorama" version = "0.4.6" @@ -310,15 +241,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5", size = 22335, upload-time = "2022-10-25T20:38:27.636Z" }, ] -[[package]] -name = "pycparser" -version = "2.22" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" }, -] - [[package]] name = "pygments" version = "2.18.0" @@ -362,7 +284,6 @@ wheels = [ name = "pytest-codspeed" source = { editable = "." } dependencies = [ - { name = "cffi" }, { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "pytest" }, { name = "rich" }, @@ -386,7 +307,6 @@ dev = [ [package.metadata] requires-dist = [ - { name = "cffi", specifier = ">=1.17.1" }, { name = "importlib-metadata", marker = "python_full_version < '3.10'", specifier = ">=8.5.0" }, { name = "pytest", specifier = ">=3.8" }, { name = "pytest-benchmark", marker = "extra == 'compat'", specifier = "~=5.0.0" },