Skip to content

Commit 76efdf6

Browse files
committed
cuda_bindings: compare explanation dicts to CUresult/cudaError_t __doc__
Add test_explanations_dict_matches_enum_member_docstrings, which checks that each hand-maintained DRIVER_CU_RESULT_EXPLANATIONS and RUNTIME_CUDA_ERROR_EXPLANATIONS entry matches the corresponding FastEnum member's __doc__ (cuda-bindings 13.2+ is said to attach the same narrative text via codegen). The comparison uses strict string equality. In current releases the dict text and __doc__ are not byte-identical: generated docstrings include Sphinx cross-references (:py:obj:...) and manual line breaks where the dicts use raw CUDA comment style (::symbol()) and single-line concatenation; some deprecated codes differ in length. So the test is marked xfail(strict=False) so CI stays green until dicts and generated docstrings share one source of truth; when they align, XPASS indicates the xfail can be removed. Skip the compare when cuda-bindings < 13.2 (major.minor). Skip members with no __doc__ (e.g. cudaErrorApiFailureBase). Helpers: _explanation_text_from_dict_value to flatten dict tuple fragments. To inspect all mismatches locally: pytest --runxfail on this test. Made-with: Cursor
1 parent 07d522d commit 76efdf6

1 file changed

Lines changed: 72 additions & 0 deletions

File tree

cuda_bindings/tests/test_enum_explanations.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import importlib
55
import importlib.metadata
6+
import textwrap
67

78
import pytest
89

@@ -13,6 +14,10 @@
1314
("runtime_cuda_error_explanations", "RUNTIME_CUDA_ERROR_EXPLANATIONS", runtime.cudaError_t),
1415
]
1516

17+
# Explanation dicts are maintained for the same toolkit as cuda-bindings; enum members
18+
# carry docstrings from code generation (reportedly aligned since cuda-bindings 13.2.0).
19+
_MIN_BINDING_VERSION_FOR_DOCSTRING_COMPARE = (13, 2)
20+
1621

1722
def _get_binding_version():
1823
try:
@@ -22,6 +27,73 @@ def _get_binding_version():
2227
return tuple(int(v) for v in major_minor)
2328

2429

30+
def _explanation_text_from_dict_value(value):
31+
"""Flatten a dict entry to a single str (entries are str or tuple of str fragments)."""
32+
if isinstance(value, tuple):
33+
return "".join(value)
34+
return value
35+
36+
37+
@pytest.mark.xfail(
38+
reason=(
39+
"Enum member __doc__ is not byte-identical to explanation dicts in current "
40+
"releases (Sphinx/RST and line breaks in __doc__ vs ::-style refs in dicts; "
41+
"some deprecated codes use a short [Deprecated] docstring). Remove xfail when "
42+
"dicts and generated docstrings share one source of truth."
43+
),
44+
strict=False,
45+
)
46+
@pytest.mark.parametrize("module_name,dict_name,enum_type", _EXPLANATION_MODULES)
47+
def test_explanations_dict_matches_enum_member_docstrings(module_name, dict_name, enum_type):
48+
"""Each explanation dict value should match the corresponding enum member's __doc__.
49+
50+
cuda-bindings 13.2+ attaches per-member documentation on driver ``CUresult`` and
51+
runtime ``cudaError_t``; this test checks it against the hand-maintained dicts.
52+
53+
If this fails, differences may include whitespace, line breaks, Sphinx/RST markup
54+
in ``__doc__`` vs raw ``::symbol()`` text in the dicts—normalizing whitespace is
55+
a possible follow-up.
56+
57+
Marked xfail while dict text and generated ``__doc__`` differ; run
58+
``pytest --runxfail`` on this test to print the full mismatch report.
59+
"""
60+
if _get_binding_version() < _MIN_BINDING_VERSION_FOR_DOCSTRING_COMPARE:
61+
pytest.skip(
62+
"Enum __doc__ vs explanation dict compare is only run for "
63+
f"cuda-bindings >= {_MIN_BINDING_VERSION_FOR_DOCSTRING_COMPARE[0]}.{_MIN_BINDING_VERSION_FOR_DOCSTRING_COMPARE[1]}"
64+
)
65+
66+
mod = importlib.import_module(f"cuda.bindings._utils.{module_name}")
67+
expl_dict = getattr(mod, dict_name)
68+
69+
mismatches = []
70+
for error in enum_type:
71+
code = int(error)
72+
assert code in expl_dict
73+
expected = _explanation_text_from_dict_value(expl_dict[code])
74+
actual = error.__doc__
75+
if actual is None:
76+
continue
77+
if expected != actual:
78+
mismatches.append((error, expected, actual))
79+
80+
if not mismatches:
81+
return
82+
83+
lines = [
84+
f"{len(mismatches)} enum member(s) where dict text != __doc__ (strict equality):",
85+
]
86+
for error, expected, actual in mismatches[:15]:
87+
lines.append(f" {error!r}")
88+
lines.append(" dict:")
89+
lines.extend(" | " + ln for ln in textwrap.wrap(repr(expected), width=100) or [""])
90+
lines.append(" __doc__:")
91+
lines.extend(" | " + ln for ln in textwrap.wrap(repr(actual), width=100) or [""])
92+
if len(mismatches) > 15:
93+
lines.append(f" ... and {len(mismatches) - 15} more")
94+
pytest.fail("\n".join(lines))
95+
96+
2597
@pytest.mark.parametrize("module_name,dict_name,enum_type", _EXPLANATION_MODULES)
2698
def test_explanations_health(module_name, dict_name, enum_type):
2799
mod = importlib.import_module(f"cuda.bindings._utils.{module_name}")

0 commit comments

Comments
 (0)