Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
85d9e66
Copy enum explanation dicts and health-check tests to cuda_bindings (…
rwgk Mar 23, 2026
f35670a
Remove enum explanation health tests from cuda_core (#1712)
rwgk Mar 23, 2026
d6b3e78
cuda_core: prefer enum explanations from cuda.bindings, keep local fa…
rwgk Mar 23, 2026
b54ec83
Add _CTK_MAJOR_MINOR_PATCH version guards and DRY up explanation test…
rwgk Mar 23, 2026
3f6c30f
Clean up test code: parametrize bindings health tests, drop no-op f-s…
rwgk Mar 23, 2026
b1645c0
Update pathfinder descriptor catalogs for cusparseLt release 0.9.0
rwgk Mar 23, 2026
fb12195
Merge branch 'main' into move_enum_explanations
rwgk Mar 23, 2026
47e9c2d
Merge branch 'main' into move_enum_explanations
rwgk Mar 24, 2026
89a2052
Merge branch 'main' into move_enum_explanations
rwgk Mar 25, 2026
6fc77b7
Delete cuda_core fallback explanation copies, import from cuda.bindin…
rwgk Mar 26, 2026
112fb41
Merge branch 'main' into move_enum_explanations
rwgk Mar 26, 2026
914ffd6
Revert to original dict names and drop _CTK_MAJOR_MINOR_PATCH (#1712)
rwgk Mar 26, 2026
07d522d
Merge branch 'main' into move_enum_explanations
rwgk Mar 31, 2026
76efdf6
cuda_bindings: compare explanation dicts to CUresult/cudaError_t __doc__
rwgk Mar 31, 2026
86e9488
cuda_bindings: add clean_enum_member_docstring helper in enum explana…
rwgk Mar 31, 2026
f4094c5
cuda_bindings: compare explanation dicts to cleaned enum __doc__ in h…
rwgk Mar 31, 2026
4adec22
cuda_bindings: improve dict/__doc__ parity test (Doxygen :: strip, de…
rwgk Mar 31, 2026
1ce9bc8
cuda_bindings: collapse wrapped hyphen spaces in clean_enum_member_do…
rwgk Mar 31, 2026
cbebba0
cuda_bindings: fix Interactions __doc__ workaround and CUDART_DRIVER …
rwgk Mar 31, 2026
ba2f65a
cuda_bindings: skip cudaErrorLaunchTimeout in dict vs cleaned __doc__…
rwgk Mar 31, 2026
2d14279
Merge branch 'main' into move_enum_explanations
rwgk Apr 1, 2026
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
2 changes: 2 additions & 0 deletions cuda_bindings/cuda/bindings/_utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE
359 changes: 359 additions & 0 deletions cuda_bindings/cuda/bindings/_utils/driver_cu_result_explanations.py

Large diffs are not rendered by default.

552 changes: 552 additions & 0 deletions cuda_bindings/cuda/bindings/_utils/runtime_cuda_error_explanations.py

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions cuda_bindings/tests/test_enum_explanations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE

import importlib
import importlib.metadata

import pytest

from cuda.bindings import driver, runtime

_EXPLANATION_MODULES = [
("driver_cu_result_explanations", driver.CUresult),
("runtime_cuda_error_explanations", runtime.cudaError_t),
]


def _get_binding_version():
try:
major_minor = importlib.metadata.version("cuda-bindings").split(".")[:2]
except importlib.metadata.PackageNotFoundError:
major_minor = importlib.metadata.version("cuda-python").split(".")[:2]
return tuple(int(v) for v in major_minor)


@pytest.mark.parametrize("module_name,enum_type", _EXPLANATION_MODULES)
def test_explanations_health(module_name, enum_type):
mod = importlib.import_module(f"cuda.bindings._utils.{module_name}")
expl_dict = mod._EXPLANATIONS

known_codes = set()
for error in enum_type:
code = int(error)
assert code in expl_dict
known_codes.add(code)

if _get_binding_version() >= (13, 0):
extra_expl = sorted(set(expl_dict.keys()) - known_codes)
assert not extra_expl
19 changes: 13 additions & 6 deletions cuda_core/cuda/core/_utils/driver_cu_result_explanations.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE

# To regenerate the dictionary below run:
# ../../../../../toolshed/reformat_cuda_enums_as_py.py /usr/local/cuda/include/cuda.h
# Replace the dictionary below with the output.
# Also update the CUDA Toolkit version number below.
# Fallback copy -- overridden from cuda.bindings below when available.
_CTK_MAJOR_MINOR_PATCH = (13, 2, 0)

# CUDA Toolkit v13.2.0
DRIVER_CU_RESULT_EXPLANATIONS = {
_FALLBACK_EXPLANATIONS = {
0: (
"The API call returned with no errors. In the case of query calls, this"
" also means that the operation being queried is complete (see"
Expand Down Expand Up @@ -356,3 +353,13 @@
),
999: "This indicates that an unknown internal error has occurred.",
}

DRIVER_CU_RESULT_EXPLANATIONS = _FALLBACK_EXPLANATIONS

# Prefer the authoritative copy from cuda.bindings when available.
try:
import cuda.bindings._utils.driver_cu_result_explanations as _authoritative
except ModuleNotFoundError:
pass
else:
DRIVER_CU_RESULT_EXPLANATIONS = _authoritative._EXPLANATIONS
19 changes: 13 additions & 6 deletions cuda_core/cuda/core/_utils/runtime_cuda_error_explanations.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE

# To regenerate the dictionary below run:
# ../../../../../toolshed/reformat_cuda_enums_as_py.py /usr/local/cuda/include/driver_types.h
# Replace the dictionary below with the output.
# Also update the CUDA Toolkit version number below.
# Fallback copy -- overridden from cuda.bindings below when available.
_CTK_MAJOR_MINOR_PATCH = (13, 2, 0)

# CUDA Toolkit v13.2.0
RUNTIME_CUDA_ERROR_EXPLANATIONS = {
_FALLBACK_EXPLANATIONS = {
0: (
"The API call returned with no errors. In the case of query calls, this"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to duplicate this error text list? Can we hoist it into a central location?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to duplicate this error text list?

Originally my proposal was to avoid this copy (see the #1712 issue description, Backward compatibility section), but @leofang argued for vendoring (see issue comments).

Can we hoist it into a central location?

Not if we want future cuda-core releases to produce the enhanced error messages even if used in combination with cuda-binding releases made before this PR was merged.

On balance, I still feel the better compromise is to delete this copy, and to change cuda_core/cuda/core/_utils/cuda_utils.pyx to skip enhancing the error messages if the dict is not in cuda-bindings. It's really only a nice-to-have that will be easy to get back by using the latest cuda-bindings.

" also means that the operation being queried is complete (see"
Expand Down Expand Up @@ -549,3 +546,13 @@
" This error return is deprecated as of CUDA 4.1."
),
}

RUNTIME_CUDA_ERROR_EXPLANATIONS = _FALLBACK_EXPLANATIONS

# Prefer the authoritative copy from cuda.bindings when available.
try:
import cuda.bindings._utils.runtime_cuda_error_explanations as _authoritative
except ModuleNotFoundError:
pass
else:
RUNTIME_CUDA_ERROR_EXPLANATIONS = _authoritative._EXPLANATIONS
63 changes: 36 additions & 27 deletions cuda_core/tests/test_cuda_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,53 @@
# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE

import dataclasses
import importlib

import pytest

from cuda.bindings import driver, runtime
from cuda.core._utils import cuda_utils
from cuda.core._utils.clear_error_support import assert_type_str_or_bytes_like, raise_code_path_meant_to_be_unreachable

_EXPLANATION_MODULES = [
("driver_cu_result_explanations", "DRIVER_CU_RESULT_EXPLANATIONS"),
("runtime_cuda_error_explanations", "RUNTIME_CUDA_ERROR_EXPLANATIONS"),
]

def test_driver_cu_result_explanations_health():
expl_dict = cuda_utils.DRIVER_CU_RESULT_EXPLANATIONS

# Ensure all CUresult enums are in expl_dict
known_codes = set()
for error in driver.CUresult:
code = int(error)
assert code in expl_dict
known_codes.add(code)

if cuda_utils.get_binding_version() >= (13, 0):
# Ensure expl_dict has no codes not known as a CUresult enum
extra_expl = sorted(set(expl_dict.keys()) - known_codes)
assert not extra_expl

@pytest.mark.parametrize("module_name,public_name", _EXPLANATION_MODULES)
def test_explanations_smoke(module_name, public_name):
expl = getattr(cuda_utils, public_name)
for code in (0, 1, 2):
assert code in expl
assert isinstance(expl[code], str)

def test_runtime_cuda_error_explanations_health():
expl_dict = cuda_utils.RUNTIME_CUDA_ERROR_EXPLANATIONS

# Ensure all cudaError_t enums are in expl_dict
known_codes = set()
for error in runtime.cudaError_t:
code = int(error)
assert code in expl_dict
known_codes.add(code)

if cuda_utils.get_binding_version() >= (13, 0):
# Ensure expl_dict has no codes not known as a cudaError_t enum
extra_expl = sorted(set(expl_dict.keys()) - known_codes)
assert not extra_expl
@pytest.mark.parametrize("module_name,public_name", _EXPLANATION_MODULES)
def test_explanations_ctk_version(module_name, public_name):
del public_name # unused
core_mod = importlib.import_module(f"cuda.core._utils.{module_name}")
try:
bindings_mod = importlib.import_module(f"cuda.bindings._utils.{module_name}")
except ModuleNotFoundError:
pytest.skip("cuda.bindings._utils not available")
bindings_path = f"cuda_bindings/cuda/bindings/_utils/{module_name}.py"
core_path = f"cuda_core/cuda/core/_utils/{module_name}.py"
if core_mod._CTK_MAJOR_MINOR_PATCH < bindings_mod._CTK_MAJOR_MINOR_PATCH:
raise RuntimeError(
f"cuda_core copy is older ({core_mod._CTK_MAJOR_MINOR_PATCH})"
f" than cuda_bindings ({bindings_mod._CTK_MAJOR_MINOR_PATCH})."
f" Please copy the _EXPLANATIONS dict from {bindings_path} to {core_path}"
)
if (
core_mod._CTK_MAJOR_MINOR_PATCH == bindings_mod._CTK_MAJOR_MINOR_PATCH
and core_mod._FALLBACK_EXPLANATIONS != bindings_mod._EXPLANATIONS
):
raise RuntimeError(
"The cuda_core copy of the cuda_bindings _EXPLANATIONS dict is out of sync"
f" (both at CTK {core_mod._CTK_MAJOR_MINOR_PATCH})."
f" Please copy the _EXPLANATIONS dict from {bindings_path} to {core_path}"
)


def test_check_driver_error():
Expand Down
Loading