From 9a403dc31240d1a876d23c50650ae9c614bc19dd Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Fri, 20 Mar 2026 15:10:08 -0400 Subject: [PATCH 01/12] Improve testing of cuda_core examples --- .github/workflows/test-wheel-linux.yml | 5 +- cuda_core/examples/cuda_graphs.py | 6 +- cuda_core/examples/gl_interop_plasma.py | 7 +- cuda_core/examples/jit_lto_fractal.py | 6 +- cuda_core/examples/memory_ops.py | 6 +- cuda_core/examples/pytorch_example.py | 6 +- cuda_core/examples/saxpy.py | 6 +- cuda_core/examples/show_device_properties.py | 6 +- .../examples/simple_multi_gpu_example.py | 6 +- cuda_core/examples/strided_memory_view_cpu.py | 6 +- cuda_core/examples/strided_memory_view_gpu.py | 6 +- cuda_core/examples/thread_block_cluster.py | 6 +- cuda_core/examples/tma_tensor_map.py | 4 + cuda_core/examples/vector_add.py | 6 +- cuda_core/pyproject.toml | 2 +- .../example_tests/test_basic_examples.py | 101 ++++++++++++++++-- cuda_core/tests/example_tests/utils.py | 53 --------- 17 files changed, 161 insertions(+), 77 deletions(-) delete mode 100644 cuda_core/tests/example_tests/utils.py diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index c5061a16eb..a69004f9c3 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -96,12 +96,15 @@ jobs: uses: nv-gha-runners/setup-proxy-cache@main continue-on-error: true + - name: Install uv + uses: astral-sh/setup-uv@v7 + - name: Install dependencies uses: ./.github/actions/install_unix_deps continue-on-error: false with: # for artifact fetching, graphics libs - dependencies: "jq wget libgl1 libegl1" + dependencies: "jq wget libgl1 libegl1 g++" dependent_exes: "jq wget" - name: Set environment variables diff --git a/cuda_core/examples/cuda_graphs.py b/cuda_core/examples/cuda_graphs.py index be23067200..ad4271aeb5 100644 --- a/cuda_core/examples/cuda_graphs.py +++ b/cuda_core/examples/cuda_graphs.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -10,6 +10,10 @@ # # ################################################################################ +# /// script +# dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] +# /// + import sys import time diff --git a/cuda_core/examples/gl_interop_plasma.py b/cuda_core/examples/gl_interop_plasma.py index 3d881a90f2..d303abdc25 100644 --- a/cuda_core/examples/gl_interop_plasma.py +++ b/cuda_core/examples/gl_interop_plasma.py @@ -53,9 +53,10 @@ # effect popular in the demoscene). The window title shows the current FPS. # Close the window or press Escape to exit. # -# Requirements -# ============ -# pip install pyglet + +# /// script +# dependencies = ["cuda_bindings", "cuda_core>0.6.0", "pyglet"] +# /// import ctypes import sys diff --git a/cuda_core/examples/jit_lto_fractal.py b/cuda_core/examples/jit_lto_fractal.py index acf96be0f0..0e182550fe 100644 --- a/cuda_core/examples/jit_lto_fractal.py +++ b/cuda_core/examples/jit_lto_fractal.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -12,6 +12,10 @@ # # ################################################################################ +# /// script +# dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] +# /// + import argparse import sys diff --git a/cuda_core/examples/memory_ops.py b/cuda_core/examples/memory_ops.py index a53f33d2df..a7bf19d1aa 100644 --- a/cuda_core/examples/memory_ops.py +++ b/cuda_core/examples/memory_ops.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -10,6 +10,10 @@ # # ################################################################################ +# /// script +# dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] +# /// + import sys import cupy as cp diff --git a/cuda_core/examples/pytorch_example.py b/cuda_core/examples/pytorch_example.py index 6909272b4d..5826c0a442 100644 --- a/cuda_core/examples/pytorch_example.py +++ b/cuda_core/examples/pytorch_example.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -9,6 +9,10 @@ # # ################################################################################ +# /// script +# dependencies = ["cuda_bindings", "cuda_core", "torch"] +# /// + import sys import torch diff --git a/cuda_core/examples/saxpy.py b/cuda_core/examples/saxpy.py index 6e5b320f90..4848ef6850 100644 --- a/cuda_core/examples/saxpy.py +++ b/cuda_core/examples/saxpy.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -10,6 +10,10 @@ # # ################################################################################ +# /// script +# dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] +# /// + import sys import cupy as cp diff --git a/cuda_core/examples/show_device_properties.py b/cuda_core/examples/show_device_properties.py index 093b89b331..566f689094 100644 --- a/cuda_core/examples/show_device_properties.py +++ b/cuda_core/examples/show_device_properties.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -9,6 +9,10 @@ # # ################################################################################ +# /// script +# dependencies = ["cuda_bindings", "cuda_core"] +# /// + import sys from cuda.core import Device, system diff --git a/cuda_core/examples/simple_multi_gpu_example.py b/cuda_core/examples/simple_multi_gpu_example.py index 236a1cca20..e4d7a1ccfb 100644 --- a/cuda_core/examples/simple_multi_gpu_example.py +++ b/cuda_core/examples/simple_multi_gpu_example.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -9,6 +9,10 @@ # # ################################################################################ +# /// script +# dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] +# /// + import sys import cupy as cp diff --git a/cuda_core/examples/strided_memory_view_cpu.py b/cuda_core/examples/strided_memory_view_cpu.py index 8482021c45..3acebac3f1 100644 --- a/cuda_core/examples/strided_memory_view_cpu.py +++ b/cuda_core/examples/strided_memory_view_cpu.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -9,6 +9,10 @@ # # ################################################################################ +# /// script +# dependencies = ["cuda_bindings", "cuda_core", "cffi", "setuptools"] +# /// + import importlib import string import sys diff --git a/cuda_core/examples/strided_memory_view_gpu.py b/cuda_core/examples/strided_memory_view_gpu.py index 0abf5d086e..061d5720ca 100644 --- a/cuda_core/examples/strided_memory_view_gpu.py +++ b/cuda_core/examples/strided_memory_view_gpu.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -9,6 +9,10 @@ # # ################################################################################ +# /// script +# dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] +# /// + import string import sys diff --git a/cuda_core/examples/thread_block_cluster.py b/cuda_core/examples/thread_block_cluster.py index 495fe882a9..cf9ad21ca7 100644 --- a/cuda_core/examples/thread_block_cluster.py +++ b/cuda_core/examples/thread_block_cluster.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -10,6 +10,10 @@ # # ################################################################################ +# /// script +# dependencies = ["cuda_bindings", "cuda_core"] +# /// + import os import sys diff --git a/cuda_core/examples/tma_tensor_map.py b/cuda_core/examples/tma_tensor_map.py index b914651089..119e281c85 100644 --- a/cuda_core/examples/tma_tensor_map.py +++ b/cuda_core/examples/tma_tensor_map.py @@ -22,6 +22,10 @@ # # ################################################################################ +# /// script +# dependencies = ["cuda_bindings", "cuda_core>0.6.0", "cupy-cuda13x"] +# /// + import os import sys diff --git a/cuda_core/examples/vector_add.py b/cuda_core/examples/vector_add.py index 3adf04882e..dd07ba1044 100644 --- a/cuda_core/examples/vector_add.py +++ b/cuda_core/examples/vector_add.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -9,6 +9,10 @@ # # ################################################################################ +# /// script +# dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] +# /// + import cupy as cp from cuda.core import Device, LaunchConfig, Program, ProgramOptions, launch diff --git a/cuda_core/pyproject.toml b/cuda_core/pyproject.toml index 9b3e5a37c5..16af61bb37 100644 --- a/cuda_core/pyproject.toml +++ b/cuda_core/pyproject.toml @@ -56,7 +56,7 @@ cu12 = ["cuda-bindings[all]==12.*"] cu13 = ["cuda-bindings[all]==13.*"] [dependency-groups] -test = ["cython>=3.2,<3.3", "setuptools", "pytest>=6.2.4", "pytest-randomly", "pytest-repeat", "pytest-rerunfailures"] +test = ["cython>=3.2,<3.3", "setuptools", "pytest>=6.2.4", "pytest-randomly", "pytest-repeat", "pytest-rerunfailures", "cffi"] ml-dtypes = ["ml-dtypes>=0.5.4,<0.6.0"] test-cu12 = [ {include-group = "ml-dtypes" }, {include-group = "test" }, "cupy-cuda12x; python_version < '3.14'", "cuda-toolkit[cudart]==12.*"] # runtime headers needed by CuPy test-cu13 = [ {include-group = "ml-dtypes" }, {include-group = "test" }, "cupy-cuda13x; python_version < '3.14'", "cuda-toolkit[cudart]==13.*"] # runtime headers needed by CuPy diff --git a/cuda_core/tests/example_tests/test_basic_examples.py b/cuda_core/tests/example_tests/test_basic_examples.py index 48f16813df..702421a27a 100644 --- a/cuda_core/tests/example_tests/test_basic_examples.py +++ b/cuda_core/tests/example_tests/test_basic_examples.py @@ -1,24 +1,109 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # If we have subcategories of examples in the future, this file can be split along those lines import glob import os +import re +import subprocess +import sys import pytest -from cuda.core import Device +from cuda.core import Device, system + +# Each example in cuda_core/examples is tested in two ways: +# +# 1) Directly running the example in the same environment as the test suite. +# This gives access to the current development version of cuda_core. +# 2) Running the example in a subprocess with "uv run" to verify that the PEP +# 723 metadata installation works correctly and that the example can be run in +# isolation from the test suite. + + +def has_compute_capability_9_or_higher() -> bool: + return Device().compute_capability >= (9, 0) + + +def has_multiple_devices() -> bool: + return system.get_num_devices() >= 2 + + +def has_display() -> bool: + # We assume that we don't want to open any windows during testing, + # so we always return False + return False + + +def uv_installed() -> bool: + try: + subprocess.run(["uv", "--version"], check=True) # noqa: S607 + except (subprocess.CalledProcessError, FileNotFoundError): + return False + return True + + +PACKAGE_REQUIREMENTS = { + "pytorch_example.py": ["torch"], + "cuda_graphs.py": ["cupy"], + "jit_lto_fractal.py": ["cupy"], + "memory_ops.py": ["cupy"], + "saxpy.py": ["cupy"], + "simple_multi_gpu_example.py": ["cupy"], + "strided_memory_view_cpu.py": ["cffi"], + "strided_memory_view_gpu.py": ["cupy"], + "tma_tensor_map.py": ["cupy"], + "vector_add.py": ["cupy"], +} + + +SYSTEM_REQUIREMENTS = { + "gl_interop_plasma.py": has_display, + "thread_block_cluster.py": has_compute_capability_9_or_higher, + "simple_multi_gpu_example.py": has_multiple_devices, +} -from .utils import run_example samples_path = os.path.join(os.path.dirname(__file__), "..", "..", "examples") -sample_files = glob.glob(samples_path + "**/*.py", recursive=True) +sample_files = [os.path.basename(x) for x in glob.glob(samples_path + "**/*.py", recursive=True)] @pytest.mark.parametrize("example", sample_files) class TestExamples: - def test_example(self, example, deinit_cuda): - run_example(samples_path, example) - if Device().device_id != 0: - Device(0).set_current() + def test_example(self, example): + package_requirements = PACKAGE_REQUIREMENTS.get(example, []) + for package in package_requirements: + try: + __import__(package) + except ImportError: + pytest.skip(f"Skipping {example} due to missing package requirement: {package}") + + system_requirement = SYSTEM_REQUIREMENTS.get(example, lambda: True) + if not system_requirement(): + pytest.skip(f"Skipping {example} due to unmet system requirement") + + example_path = os.path.join(samples_path, example) + process = subprocess.run([sys.executable, example_path], capture_output=True) # noqa: S603 + if process.returncode != 0: + print(process.stdout.decode()) + print(process.stderr.decode(), file=sys.stderr) + raise AssertionError(f"Example failed with return code {process.returncode} ({example})") + + @pytest.mark.skipif(not uv_installed(), reason="uv is required to test PEP 723 metadata installation") + def test_example_pep723(self, example): + system_requirement = SYSTEM_REQUIREMENTS.get(example, lambda: True) + if not system_requirement(): + pytest.skip(f"Skipping {example} due to unmet system requirement") + + example_path = os.path.join(samples_path, example) + process = subprocess.run(["uv", "run", example_path], capture_output=True) # noqa: S603, S607 + if process.returncode != 0: + # This example requires a development version of cuda_core, so requirements can't be met. + # That's ok, it was tested in the other test, so we just skip it instead of failing. + if re.match(process.stderr.decode(), "Because only cuda-(core|bindings)"): + pytest.skip(f"Skipping {example} due to unmet PEP 723 requirement") + + print(process.stdout.decode()) + print(process.stderr.decode(), file=sys.stderr) + raise AssertionError(f"Example failed with return code {process.returncode} ({example})") diff --git a/cuda_core/tests/example_tests/utils.py b/cuda_core/tests/example_tests/utils.py deleted file mode 100644 index 9b5dc57e5f..0000000000 --- a/cuda_core/tests/example_tests/utils.py +++ /dev/null @@ -1,53 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -import gc -import os -import sys - -import pytest - - -class SampleTestError(Exception): - pass - - -def parse_python_script(filepath): - if not filepath.endswith(".py"): - raise ValueError(f"{filepath} not supported") - with open(filepath, encoding="utf-8") as f: - script = f.read() - return script - - -def run_example(samples_path, filename, env=None): - fullpath = os.path.join(samples_path, filename) - script = parse_python_script(fullpath) - try: - old_argv = sys.argv - sys.argv = [fullpath] - old_sys_path = sys.path.copy() - sys.path.append(samples_path) - # TODO: Refactor the examples to give them a common callable `main()` to avoid needing to use exec here? - exec(script, env if env else {}) # noqa: S102 - except ImportError as e: - # for samples requiring any of optional dependencies - for m in ("cupy", "torch"): - if f"No module named '{m}'" in str(e): - pytest.skip(f"{m} not installed, skipping related tests") - break - else: - raise - except SystemExit: - # for samples that early return due to any missing requirements - pytest.skip(f"skip {filename}") - except Exception as e: - msg = "\n" - msg += f"Got error ({filename}):\n" - msg += str(e) - raise SampleTestError(msg) from e - finally: - sys.path = old_sys_path - sys.argv = old_argv - # further reduce the memory watermark - gc.collect() From 9b2c22bec32cbe9e33650c549a59a04dc9b3aed1 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Fri, 20 Mar 2026 15:34:25 -0400 Subject: [PATCH 02/12] More fixes --- .../example_tests/test_basic_examples.py | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/cuda_core/tests/example_tests/test_basic_examples.py b/cuda_core/tests/example_tests/test_basic_examples.py index 702421a27a..17849a3173 100644 --- a/cuda_core/tests/example_tests/test_basic_examples.py +++ b/cuda_core/tests/example_tests/test_basic_examples.py @@ -5,6 +5,7 @@ import glob import os +import platform import re import subprocess import sys @@ -18,8 +19,8 @@ # 1) Directly running the example in the same environment as the test suite. # This gives access to the current development version of cuda_core. # 2) Running the example in a subprocess with "uv run" to verify that the PEP -# 723 metadata installation works correctly and that the example can be run in -# isolation from the test suite. +# 723 metadata works correctly and that the example can be run in isolation from +# the test suite. def has_compute_capability_9_or_higher() -> bool: @@ -36,6 +37,14 @@ def has_display() -> bool: return False +def is_not_windows() -> bool: + return sys.platform != "win32" + + +def is_x86_64() -> bool: + return platform.machine() == "x86_64" + + def uv_installed() -> bool: try: subprocess.run(["uv", "--version"], check=True) # noqa: S607 @@ -45,10 +54,10 @@ def uv_installed() -> bool: PACKAGE_REQUIREMENTS = { - "pytorch_example.py": ["torch"], "cuda_graphs.py": ["cupy"], "jit_lto_fractal.py": ["cupy"], "memory_ops.py": ["cupy"], + "pytorch_example.py": ["torch"], "saxpy.py": ["cupy"], "simple_multi_gpu_example.py": ["cupy"], "strided_memory_view_cpu.py": ["cffi"], @@ -60,8 +69,10 @@ def uv_installed() -> bool: SYSTEM_REQUIREMENTS = { "gl_interop_plasma.py": has_display, - "thread_block_cluster.py": has_compute_capability_9_or_higher, + "pytorch_example.py": is_x86_64, # PyTorch only provides CUDA support for x86_64 "simple_multi_gpu_example.py": has_multiple_devices, + "strided_memory_view_cpu.py": is_not_windows, + "thread_block_cluster.py": has_compute_capability_9_or_higher, } @@ -86,11 +97,14 @@ def test_example(self, example): example_path = os.path.join(samples_path, example) process = subprocess.run([sys.executable, example_path], capture_output=True) # noqa: S603 if process.returncode != 0: - print(process.stdout.decode()) - print(process.stderr.decode(), file=sys.stderr) - raise AssertionError(f"Example failed with return code {process.returncode} ({example})") + if process.stdout: + print(process.stdout.decode()) + if process.stderr: + print(process.stderr.decode(), file=sys.stderr) + raise AssertionError(f"`{example}` failed ({process.returncode})") @pytest.mark.skipif(not uv_installed(), reason="uv is required to test PEP 723 metadata installation") + @pytest.mark.skipif(sys.platform == "win32", reason="uv does not currently work on Windows in CI") def test_example_pep723(self, example): system_requirement = SYSTEM_REQUIREMENTS.get(example, lambda: True) if not system_requirement(): @@ -101,9 +115,11 @@ def test_example_pep723(self, example): if process.returncode != 0: # This example requires a development version of cuda_core, so requirements can't be met. # That's ok, it was tested in the other test, so we just skip it instead of failing. - if re.match(process.stderr.decode(), "Because only cuda-(core|bindings)"): + if re.search("Because only cuda-(core)|(bindings)", process.stderr.decode()): pytest.skip(f"Skipping {example} due to unmet PEP 723 requirement") - print(process.stdout.decode()) - print(process.stderr.decode(), file=sys.stderr) - raise AssertionError(f"Example failed with return code {process.returncode} ({example})") + if process.stdout: + print(process.stdout.decode()) + if process.stderr: + print(process.stderr.decode(), file=sys.stderr) + raise AssertionError(f"`uv run {example}` failed ({process.returncode})") From ce6c2c8a1d7391d3c3b4b7fc073c186978c649cb Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Fri, 20 Mar 2026 15:51:44 -0400 Subject: [PATCH 03/12] Try to get more info --- .../tests/example_tests/test_basic_examples.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/cuda_core/tests/example_tests/test_basic_examples.py b/cuda_core/tests/example_tests/test_basic_examples.py index 17849a3173..85e3a6897a 100644 --- a/cuda_core/tests/example_tests/test_basic_examples.py +++ b/cuda_core/tests/example_tests/test_basic_examples.py @@ -6,7 +6,6 @@ import glob import os import platform -import re import subprocess import sys @@ -104,19 +103,24 @@ def test_example(self, example): raise AssertionError(f"`{example}` failed ({process.returncode})") @pytest.mark.skipif(not uv_installed(), reason="uv is required to test PEP 723 metadata installation") - @pytest.mark.skipif(sys.platform == "win32", reason="uv does not currently work on Windows in CI") def test_example_pep723(self, example): system_requirement = SYSTEM_REQUIREMENTS.get(example, lambda: True) if not system_requirement(): pytest.skip(f"Skipping {example} due to unmet system requirement") example_path = os.path.join(samples_path, example) - process = subprocess.run(["uv", "run", example_path], capture_output=True) # noqa: S603, S607 + + # Have uv use the same version of Python that is running the test suite, + # not because they have to match but to give Python version coverage in CI. + version_info = sys.version_info + py_version = f"{version_info.major}.{version_info.minor}" + + process = subprocess.run(["uv", "run", "--python", py_version, example_path], capture_output=True) # noqa: S603, S607 if process.returncode != 0: # This example requires a development version of cuda_core, so requirements can't be met. # That's ok, it was tested in the other test, so we just skip it instead of failing. - if re.search("Because only cuda-(core)|(bindings)", process.stderr.decode()): - pytest.skip(f"Skipping {example} due to unmet PEP 723 requirement") + # if re.search("Because only cuda-(core)|(bindings)", process.stderr.decode()): + # pytest.skip(f"Skipping {example} due to unmet PEP 723 requirement") if process.stdout: print(process.stdout.decode()) From 0c91f230f36a7d8e2d3f50e3bcebd7a4d6ba9044 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Fri, 20 Mar 2026 16:21:47 -0400 Subject: [PATCH 04/12] Windows fix --- cuda_core/examples/cuda_graphs.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cuda_core/examples/cuda_graphs.py b/cuda_core/examples/cuda_graphs.py index ad4271aeb5..de9c0bcdbd 100644 --- a/cuda_core/examples/cuda_graphs.py +++ b/cuda_core/examples/cuda_graphs.py @@ -125,6 +125,9 @@ def main(): end_time = time.time() graph_execution_time = end_time - start_time + if graph_execution_time == 0.0: + print("Graph execution time is too fast to measure accurately.") + graph_execution_time = 1e-9 # Assign a small value to avoid division by zero in speedup calculation print(f"Graph execution time: {graph_execution_time:.6f} seconds") # Verify results From 05e87cd39c403d652fdeb9f926b7f3b0b9802b0c Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Fri, 20 Mar 2026 16:23:02 -0400 Subject: [PATCH 05/12] Put check back in --- cuda_core/tests/example_tests/test_basic_examples.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cuda_core/tests/example_tests/test_basic_examples.py b/cuda_core/tests/example_tests/test_basic_examples.py index 85e3a6897a..d296978323 100644 --- a/cuda_core/tests/example_tests/test_basic_examples.py +++ b/cuda_core/tests/example_tests/test_basic_examples.py @@ -6,6 +6,7 @@ import glob import os import platform +import re import subprocess import sys @@ -119,8 +120,8 @@ def test_example_pep723(self, example): if process.returncode != 0: # This example requires a development version of cuda_core, so requirements can't be met. # That's ok, it was tested in the other test, so we just skip it instead of failing. - # if re.search("Because only cuda-(core)|(bindings)", process.stderr.decode()): - # pytest.skip(f"Skipping {example} due to unmet PEP 723 requirement") + if re.search("Because only cuda-(core)|(bindings)", process.stderr.decode()): + pytest.skip(f"Skipping {example} due to unmet PEP 723 requirement") if process.stdout: print(process.stdout.decode()) From 74c51bcb6fa15ee17ab82eacde707ba3c52c2b40 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Mon, 23 Mar 2026 10:18:04 -0400 Subject: [PATCH 06/12] Try to determine CUDA_PATH etc. --- cuda_core/examples/thread_block_cluster.py | 1 + .../example_tests/test_basic_examples.py | 92 +++++++++---------- 2 files changed, 46 insertions(+), 47 deletions(-) diff --git a/cuda_core/examples/thread_block_cluster.py b/cuda_core/examples/thread_block_cluster.py index cf9ad21ca7..2a4360834e 100644 --- a/cuda_core/examples/thread_block_cluster.py +++ b/cuda_core/examples/thread_block_cluster.py @@ -71,6 +71,7 @@ def main(): cuda_path = os.environ.get("CUDA_PATH", os.environ.get("CUDA_HOME")) if cuda_path is None: + print(os.environ) print("this example requires a valid CUDA_PATH environment variable set", file=sys.stderr) sys.exit(1) cuda_include = os.path.join(cuda_path, "include") diff --git a/cuda_core/tests/example_tests/test_basic_examples.py b/cuda_core/tests/example_tests/test_basic_examples.py index d296978323..fae9c8da8b 100644 --- a/cuda_core/tests/example_tests/test_basic_examples.py +++ b/cuda_core/tests/example_tests/test_basic_examples.py @@ -81,50 +81,48 @@ def uv_installed() -> bool: @pytest.mark.parametrize("example", sample_files) -class TestExamples: - def test_example(self, example): - package_requirements = PACKAGE_REQUIREMENTS.get(example, []) - for package in package_requirements: - try: - __import__(package) - except ImportError: - pytest.skip(f"Skipping {example} due to missing package requirement: {package}") - - system_requirement = SYSTEM_REQUIREMENTS.get(example, lambda: True) - if not system_requirement(): - pytest.skip(f"Skipping {example} due to unmet system requirement") - - example_path = os.path.join(samples_path, example) - process = subprocess.run([sys.executable, example_path], capture_output=True) # noqa: S603 - if process.returncode != 0: - if process.stdout: - print(process.stdout.decode()) - if process.stderr: - print(process.stderr.decode(), file=sys.stderr) - raise AssertionError(f"`{example}` failed ({process.returncode})") - - @pytest.mark.skipif(not uv_installed(), reason="uv is required to test PEP 723 metadata installation") - def test_example_pep723(self, example): - system_requirement = SYSTEM_REQUIREMENTS.get(example, lambda: True) - if not system_requirement(): - pytest.skip(f"Skipping {example} due to unmet system requirement") - - example_path = os.path.join(samples_path, example) - - # Have uv use the same version of Python that is running the test suite, - # not because they have to match but to give Python version coverage in CI. - version_info = sys.version_info - py_version = f"{version_info.major}.{version_info.minor}" - - process = subprocess.run(["uv", "run", "--python", py_version, example_path], capture_output=True) # noqa: S603, S607 - if process.returncode != 0: - # This example requires a development version of cuda_core, so requirements can't be met. - # That's ok, it was tested in the other test, so we just skip it instead of failing. - if re.search("Because only cuda-(core)|(bindings)", process.stderr.decode()): - pytest.skip(f"Skipping {example} due to unmet PEP 723 requirement") - - if process.stdout: - print(process.stdout.decode()) - if process.stderr: - print(process.stderr.decode(), file=sys.stderr) - raise AssertionError(f"`uv run {example}` failed ({process.returncode})") +def test_example(example): + package_requirements = PACKAGE_REQUIREMENTS.get(example, []) + for package in package_requirements: + pytest.importorskip(package, reason=f"Skipping {example} due to missing package requirement: {package}") + + system_requirement = SYSTEM_REQUIREMENTS.get(example, lambda: True) + if not system_requirement(): + pytest.skip(f"Skipping {example} due to unmet system requirement") + + example_path = os.path.join(samples_path, example) + process = subprocess.run([sys.executable, example_path], capture_output=True) # noqa: S603 + if process.returncode != 0: + if process.stdout: + print(process.stdout.decode()) + if process.stderr: + print(process.stderr.decode(), file=sys.stderr) + raise AssertionError(f"`{example}` failed ({process.returncode})") + + +@pytest.mark.parametrize("example", sample_files) +@pytest.mark.skipif(not uv_installed(), reason="uv is required to test PEP 723 metadata installation") +def test_example_pep723(example): + system_requirement = SYSTEM_REQUIREMENTS.get(example, lambda: True) + if not system_requirement(): + pytest.skip(f"Skipping {example} due to unmet system requirement") + + example_path = os.path.join(samples_path, example) + + # Have uv use the same version of Python that is running the test suite, + # not because they have to match but to give Python version coverage in CI. + version_info = sys.version_info + py_version = f"{version_info.major}.{version_info.minor}" + + process = subprocess.run(["uv", "run", "--python", py_version, example_path], capture_output=True) # noqa: S603, S607 + if process.returncode != 0: + # This example requires a development version of cuda_core, so requirements can't be met. + # That's ok, it was tested in the other test, so we just skip it instead of failing. + if re.search("Because only cuda-(core)|(bindings)", process.stderr.decode()): + pytest.skip(f"Skipping {example} due to unmet PEP 723 requirement") + + if process.stdout: + print(process.stdout.decode()) + if process.stderr: + print(process.stderr.decode(), file=sys.stderr) + raise AssertionError(f"`uv run {example}` failed ({process.returncode})") From ba309541db5c835610287dc3f1294c68646b0239 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Mon, 23 Mar 2026 11:05:46 -0400 Subject: [PATCH 07/12] Trying to debug --- .github/workflows/test-wheel-linux.yml | 2 +- cuda_core/tests/example_tests/test_basic_examples.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index a69004f9c3..2fe12a3b99 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -103,7 +103,7 @@ jobs: uses: ./.github/actions/install_unix_deps continue-on-error: false with: - # for artifact fetching, graphics libs + # for artifact fetching, graphics libs, g++ required for cffi in example dependencies: "jq wget libgl1 libegl1 g++" dependent_exes: "jq wget" diff --git a/cuda_core/tests/example_tests/test_basic_examples.py b/cuda_core/tests/example_tests/test_basic_examples.py index fae9c8da8b..88886865f8 100644 --- a/cuda_core/tests/example_tests/test_basic_examples.py +++ b/cuda_core/tests/example_tests/test_basic_examples.py @@ -119,7 +119,9 @@ def test_example_pep723(example): # This example requires a development version of cuda_core, so requirements can't be met. # That's ok, it was tested in the other test, so we just skip it instead of failing. if re.search("Because only cuda-(core)|(bindings)", process.stderr.decode()): - pytest.skip(f"Skipping {example} due to unmet PEP 723 requirement") + print("FOUND FAIL TAG") + # if re.search("Because only cuda-(core)|(bindings)", process.stderr.decode()): + # pytest.skip(f"Skipping {example} due to unmet PEP 723 requirement") if process.stdout: print(process.stdout.decode()) From c041b3fc5adf02a2dc8b6e97914f1d47a136fa5d Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Mon, 23 Mar 2026 12:10:29 -0400 Subject: [PATCH 08/12] Progress --- cuda_core/tests/example_tests/test_basic_examples.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cuda_core/tests/example_tests/test_basic_examples.py b/cuda_core/tests/example_tests/test_basic_examples.py index 88886865f8..092998602b 100644 --- a/cuda_core/tests/example_tests/test_basic_examples.py +++ b/cuda_core/tests/example_tests/test_basic_examples.py @@ -114,14 +114,14 @@ def test_example_pep723(example): version_info = sys.version_info py_version = f"{version_info.major}.{version_info.minor}" + print("Parent process environment:", os.environ) + process = subprocess.run(["uv", "run", "--python", py_version, example_path], capture_output=True) # noqa: S603, S607 if process.returncode != 0: # This example requires a development version of cuda_core, so requirements can't be met. # That's ok, it was tested in the other test, so we just skip it instead of failing. - if re.search("Because only cuda-(core)|(bindings)", process.stderr.decode()): - print("FOUND FAIL TAG") - # if re.search("Because only cuda-(core)|(bindings)", process.stderr.decode()): - # pytest.skip(f"Skipping {example} due to unmet PEP 723 requirement") + if re.search("Because only cuda-((core)|(bindings))", process.stderr.decode()): + pytest.skip(f"Skipping {example} due to unmet PEP 723 requirement") if process.stdout: print(process.stdout.decode()) From c0e9a6e9596f78125d7f96c94d5f6f6e3b0d382a Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Mon, 23 Mar 2026 13:53:29 -0400 Subject: [PATCH 09/12] Trying to get more info --- cuda_core/examples/saxpy.py | 7 +++++++ cuda_core/tests/example_tests/test_basic_examples.py | 7 ++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/cuda_core/examples/saxpy.py b/cuda_core/examples/saxpy.py index 4848ef6850..0f0b028786 100644 --- a/cuda_core/examples/saxpy.py +++ b/cuda_core/examples/saxpy.py @@ -14,8 +14,15 @@ # dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] # /// + import sys +from cuda import pathfinder + +print(pathfinder.load_nvidia_dynamic_lib("nvrtc")) + +sys.exit(1) + import cupy as cp from cuda.core import Device, LaunchConfig, Program, ProgramOptions, launch diff --git a/cuda_core/tests/example_tests/test_basic_examples.py b/cuda_core/tests/example_tests/test_basic_examples.py index 092998602b..01de655408 100644 --- a/cuda_core/tests/example_tests/test_basic_examples.py +++ b/cuda_core/tests/example_tests/test_basic_examples.py @@ -53,6 +53,10 @@ def uv_installed() -> bool: return True +def has_cuda_path() -> bool: + return os.environ.get("CUDA_PATH", os.environ.get("CUDA_HOME")) is not None + + PACKAGE_REQUIREMENTS = { "cuda_graphs.py": ["cupy"], "jit_lto_fractal.py": ["cupy"], @@ -72,7 +76,8 @@ def uv_installed() -> bool: "pytorch_example.py": is_x86_64, # PyTorch only provides CUDA support for x86_64 "simple_multi_gpu_example.py": has_multiple_devices, "strided_memory_view_cpu.py": is_not_windows, - "thread_block_cluster.py": has_compute_capability_9_or_higher, + "thread_block_cluster.py": lambda: has_compute_capability_9_or_higher() and has_cuda_path(), + "tma_tensor_map.py": has_cuda_path, } From 26df2f9b5440bb56696edda077d4514958a2968f Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Mon, 23 Mar 2026 14:09:46 -0400 Subject: [PATCH 10/12] More info --- cuda_core/examples/saxpy.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cuda_core/examples/saxpy.py b/cuda_core/examples/saxpy.py index 0f0b028786..a1597c7634 100644 --- a/cuda_core/examples/saxpy.py +++ b/cuda_core/examples/saxpy.py @@ -11,7 +11,7 @@ # ################################################################################ # /// script -# dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] +# dependencies = ["cuda_bindings", "cuda_core", "nvidia-cuda-runtime", "cupy-cuda13x"] # /// @@ -21,8 +21,6 @@ print(pathfinder.load_nvidia_dynamic_lib("nvrtc")) -sys.exit(1) - import cupy as cp from cuda.core import Device, LaunchConfig, Program, ProgramOptions, launch From b79ba4359043260982ca225f8b442299c1138ec6 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Mon, 23 Mar 2026 14:10:42 -0400 Subject: [PATCH 11/12] Attempted fix --- cuda_core/examples/saxpy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_core/examples/saxpy.py b/cuda_core/examples/saxpy.py index a1597c7634..85737f84d4 100644 --- a/cuda_core/examples/saxpy.py +++ b/cuda_core/examples/saxpy.py @@ -11,7 +11,7 @@ # ################################################################################ # /// script -# dependencies = ["cuda_bindings", "cuda_core", "nvidia-cuda-runtime", "cupy-cuda13x"] +# dependencies = ["cuda_bindings", "cuda_core", "nvidia-cuda-nvrtc", "cupy-cuda13x"] # /// From f03471d822914a6e84d7ac6a27125e7d1f6c8c19 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Mon, 23 Mar 2026 14:50:37 -0400 Subject: [PATCH 12/12] Handle metadata automatically --- cuda_core/examples/cuda_graphs.py | 2 +- cuda_core/examples/jit_lto_fractal.py | 2 +- cuda_core/examples/memory_ops.py | 2 +- cuda_core/examples/strided_memory_view_gpu.py | 2 +- cuda_core/examples/vector_add.py | 2 +- .../example_tests/test_basic_examples.py | 62 ++++++++++++------- 6 files changed, 45 insertions(+), 27 deletions(-) diff --git a/cuda_core/examples/cuda_graphs.py b/cuda_core/examples/cuda_graphs.py index de9c0bcdbd..57321dd48c 100644 --- a/cuda_core/examples/cuda_graphs.py +++ b/cuda_core/examples/cuda_graphs.py @@ -11,7 +11,7 @@ # ################################################################################ # /// script -# dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] +# dependencies = ["cuda_bindings", "cuda_core", "nvidia-cuda-nvrtc", "cupy-cuda13x"] # /// import sys diff --git a/cuda_core/examples/jit_lto_fractal.py b/cuda_core/examples/jit_lto_fractal.py index 0e182550fe..98fd402ee0 100644 --- a/cuda_core/examples/jit_lto_fractal.py +++ b/cuda_core/examples/jit_lto_fractal.py @@ -13,7 +13,7 @@ # ################################################################################ # /// script -# dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] +# dependencies = ["cuda_bindings", "cuda_core", "nvidia-cuda-nvrtc", "cupy-cuda13x"] # /// import argparse diff --git a/cuda_core/examples/memory_ops.py b/cuda_core/examples/memory_ops.py index a7bf19d1aa..438c40b333 100644 --- a/cuda_core/examples/memory_ops.py +++ b/cuda_core/examples/memory_ops.py @@ -11,7 +11,7 @@ # ################################################################################ # /// script -# dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] +# dependencies = ["cuda_bindings", "cuda_core", "nvidia-cuda-nvrtc", "cupy-cuda13x"] # /// import sys diff --git a/cuda_core/examples/strided_memory_view_gpu.py b/cuda_core/examples/strided_memory_view_gpu.py index 061d5720ca..b481ae8060 100644 --- a/cuda_core/examples/strided_memory_view_gpu.py +++ b/cuda_core/examples/strided_memory_view_gpu.py @@ -10,7 +10,7 @@ # ################################################################################ # /// script -# dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] +# dependencies = ["cuda_bindings", "cuda_core", "nvidia-cuda-nvrtc", "cupy-cuda13x"] # /// import string diff --git a/cuda_core/examples/vector_add.py b/cuda_core/examples/vector_add.py index dd07ba1044..adb2bebcf8 100644 --- a/cuda_core/examples/vector_add.py +++ b/cuda_core/examples/vector_add.py @@ -10,7 +10,7 @@ # ################################################################################ # /// script -# dependencies = ["cuda_bindings", "cuda_core", "cupy-cuda13x"] +# dependencies = ["cuda_bindings", "cuda_core", "nvidia-cuda-nvrtc", "cupy-cuda13x"] # /// import cupy as cp diff --git a/cuda_core/tests/example_tests/test_basic_examples.py b/cuda_core/tests/example_tests/test_basic_examples.py index 01de655408..f2d09a5068 100644 --- a/cuda_core/tests/example_tests/test_basic_examples.py +++ b/cuda_core/tests/example_tests/test_basic_examples.py @@ -4,6 +4,7 @@ # If we have subcategories of examples in the future, this file can be split along those lines import glob +import importlib.metadata import os import platform import re @@ -57,23 +58,15 @@ def has_cuda_path() -> bool: return os.environ.get("CUDA_PATH", os.environ.get("CUDA_HOME")) is not None -PACKAGE_REQUIREMENTS = { - "cuda_graphs.py": ["cupy"], - "jit_lto_fractal.py": ["cupy"], - "memory_ops.py": ["cupy"], - "pytorch_example.py": ["torch"], - "saxpy.py": ["cupy"], - "simple_multi_gpu_example.py": ["cupy"], - "strided_memory_view_cpu.py": ["cffi"], - "strided_memory_view_gpu.py": ["cupy"], - "tma_tensor_map.py": ["cupy"], - "vector_add.py": ["cupy"], -} +# Specific system requirements for each of the examples. SYSTEM_REQUIREMENTS = { "gl_interop_plasma.py": has_display, - "pytorch_example.py": is_x86_64, # PyTorch only provides CUDA support for x86_64 + "pytorch_example.py": lambda: ( + has_compute_capability_9_or_higher() and is_x86_64() + ), # PyTorch only provides CUDA support for x86_64 + "saxpy.py": has_compute_capability_9_or_higher, "simple_multi_gpu_example.py": has_multiple_devices, "strided_memory_view_cpu.py": is_not_windows, "thread_block_cluster.py": lambda: has_compute_capability_9_or_higher() and has_cuda_path(), @@ -85,17 +78,44 @@ def has_cuda_path() -> bool: sample_files = [os.path.basename(x) for x in glob.glob(samples_path + "**/*.py", recursive=True)] +def has_package_requirements_or_skip(example): + with open(example, encoding="utf-8") as f: + content = f.read() + + # The canonical regex as defined in PEP 723 + pep723 = re.search(r"(?m)^# /// (?P[a-zA-Z0-9-]+)$\s(?P(^#(| .*)$\s)+)^# ///$", content) + if not pep723: + return + + metadata = {} + for line in pep723.group("content").splitlines(): + line = line.lstrip("# ").rstrip() + if not line: + continue + key, value = line.split("=", 1) + key = key.strip() + value = value.strip() + metadata[key] = value + + if "dependencies" in metadata: + dependencies = eval(metadata["dependencies"]) # noqa: S307 + for dependency in dependencies: + name = re.match("[a-zA-Z0-9_-]+", dependency) + try: + importlib.metadata.distribution(name.string) + except importlib.metadata.PackageNotFoundError: + pytest.skip(f"Skipping {example} due to missing package requirement: {name}") + + @pytest.mark.parametrize("example", sample_files) def test_example(example): - package_requirements = PACKAGE_REQUIREMENTS.get(example, []) - for package in package_requirements: - pytest.importorskip(package, reason=f"Skipping {example} due to missing package requirement: {package}") + example_path = os.path.join(samples_path, example) + has_package_requirements_or_skip(example_path) system_requirement = SYSTEM_REQUIREMENTS.get(example, lambda: True) if not system_requirement(): pytest.skip(f"Skipping {example} due to unmet system requirement") - example_path = os.path.join(samples_path, example) process = subprocess.run([sys.executable, example_path], capture_output=True) # noqa: S603 if process.returncode != 0: if process.stdout: @@ -106,21 +126,19 @@ def test_example(example): @pytest.mark.parametrize("example", sample_files) -@pytest.mark.skipif(not uv_installed(), reason="uv is required to test PEP 723 metadata installation") +@pytest.mark.skipif(not uv_installed(), reason="uv is required to test PEP 723 metadata") def test_example_pep723(example): + example_path = os.path.join(samples_path, example) + system_requirement = SYSTEM_REQUIREMENTS.get(example, lambda: True) if not system_requirement(): pytest.skip(f"Skipping {example} due to unmet system requirement") - example_path = os.path.join(samples_path, example) - # Have uv use the same version of Python that is running the test suite, # not because they have to match but to give Python version coverage in CI. version_info = sys.version_info py_version = f"{version_info.major}.{version_info.minor}" - print("Parent process environment:", os.environ) - process = subprocess.run(["uv", "run", "--python", py_version, example_path], capture_output=True) # noqa: S603, S607 if process.returncode != 0: # This example requires a development version of cuda_core, so requirements can't be met.