Skip to content

Commit f4094c5

Browse files
committed
cuda_bindings: compare explanation dicts to cleaned enum __doc__ in health test
Add _explanation_dict_text_for_cleaned_doc_compare to normalize dict strings for parity with clean_enum_member_docstring: strip Doxygen-style :: before name( and collapse whitespace. Rename test_explanations_dict_matches_enum_member_docstrings to test_explanations_dict_matches_cleaned_enum_docstrings; compare normalized dict text to clean_enum_member_docstring(__doc__) instead of raw __doc__. Update xfail reason and failure-report labels. Give explicit pytest.param ids on test_clean_enum_member_docstring_examples for readable node ids (ruff/pre-commit friendly). Made-with: Cursor
1 parent 86e9488 commit f4094c5

1 file changed

Lines changed: 38 additions & 25 deletions

File tree

cuda_bindings/tests/test_enum_explanations.py

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ def _explanation_text_from_dict_value(value):
3535
return value
3636

3737

38+
def _explanation_dict_text_for_cleaned_doc_compare(value) -> str:
39+
"""Normalize hand-maintained dict text to compare with ``clean_enum_member_docstring`` output.
40+
41+
Dicts follow CUDA header comments (``::cuInit()``-style refs); cleaned enum ``__doc__``
42+
uses plain names after Sphinx role stripping. Strip a leading ``::`` before ``name(`` and
43+
collapse whitespace so both sides use the same conventions as ``clean_enum_member_docstring``.
44+
"""
45+
s = _explanation_text_from_dict_value(value)
46+
s = re.sub(r"::([a-zA-Z_][a-zA-Z0-9_]*\()", r"\1", s)
47+
s = re.sub(r"\s+", " ", s).strip()
48+
return s
49+
50+
3851
def clean_enum_member_docstring(doc: str | None) -> str | None:
3952
"""Turn a FastEnum member ``__doc__`` into plain text for display or fallback logic.
4053
@@ -68,18 +81,20 @@ def clean_enum_member_docstring(doc: str | None) -> str | None:
6881
@pytest.mark.parametrize(
6982
("raw", "expected"),
7083
[
71-
("a\nb c", "a b c"),
72-
(" x \n ", "x"),
73-
(
84+
pytest.param("a\nb c", "a b c", id="collapse_whitespace"),
85+
pytest.param(" x \n ", "x", id="strip_padding"),
86+
pytest.param(
7487
"see\n:py:obj:`~.cuInit()` or :py:obj:`cuCtxDestroy()`",
7588
"see cuInit() or cuCtxDestroy()",
89+
id="sphinx_py_obj_roles",
7690
),
77-
(
91+
pytest.param(
7892
"x :py:func:`~.cudaMalloc()` y",
7993
"x cudaMalloc() y",
94+
id="sphinx_py_func_role",
8095
),
81-
("**Note:** text", "Note: text"),
82-
("[Deprecated]\n", "[Deprecated]"),
96+
pytest.param("**Note:** text", "Note: text", id="strip_bold"),
97+
pytest.param("[Deprecated]\n", "[Deprecated]", id="deprecated_line"),
8398
],
8499
)
85100
def test_clean_enum_member_docstring_examples(raw, expected):
@@ -92,26 +107,23 @@ def test_clean_enum_member_docstring_none_input():
92107

93108
@pytest.mark.xfail(
94109
reason=(
95-
"Enum member __doc__ is not byte-identical to explanation dicts in current "
96-
"releases (Sphinx/RST and line breaks in __doc__ vs ::-style refs in dicts; "
97-
"some deprecated codes use a short [Deprecated] docstring). Remove xfail when "
98-
"dicts and generated docstrings share one source of truth."
110+
"Even after clean_enum_member_docstring and dict-side ::/whitespace alignment, "
111+
"some members still differ (e.g. [Deprecated] stub vs full paragraph in dict; "
112+
"wording drift). Remove xfail when dicts and generated docstrings share one source."
99113
),
100114
strict=False,
101115
)
102116
@pytest.mark.parametrize("module_name,dict_name,enum_type", _EXPLANATION_MODULES)
103-
def test_explanations_dict_matches_enum_member_docstrings(module_name, dict_name, enum_type):
104-
"""Each explanation dict value should match the corresponding enum member's __doc__.
117+
def test_explanations_dict_matches_cleaned_enum_docstrings(module_name, dict_name, enum_type):
118+
"""Hand-maintained explanation dict entries should match cleaned enum ``__doc__`` text.
105119
106120
cuda-bindings 13.2+ attaches per-member documentation on driver ``CUresult`` and
107-
runtime ``cudaError_t``; this test checks it against the hand-maintained dicts.
108-
109-
If this fails, differences may include whitespace, line breaks, Sphinx/RST markup
110-
in ``__doc__`` vs raw ``::symbol()`` text in the dicts—normalizing whitespace is
111-
a possible follow-up.
121+
runtime ``cudaError_t``. This compares ``clean_enum_member_docstring(member.__doc__)``
122+
to dict text normalized with ``_explanation_dict_text_for_cleaned_doc_compare`` (same
123+
whitespace rules; strip Doxygen ``::`` before ``name(`` to align with Sphinx output).
112124
113-
Marked xfail while dict text and generated ``__doc__`` differ; run
114-
``pytest --runxfail`` on this test to print the full mismatch report.
125+
Marked xfail while mismatches remain; run ``pytest --runxfail`` on this test for the
126+
full mismatch report (normalized dict vs cleaned ``__doc__``).
115127
"""
116128
if _get_binding_version() < _MIN_BINDING_VERSION_FOR_DOCSTRING_COMPARE:
117129
pytest.skip(
@@ -126,24 +138,25 @@ def test_explanations_dict_matches_enum_member_docstrings(module_name, dict_name
126138
for error in enum_type:
127139
code = int(error)
128140
assert code in expl_dict
129-
expected = _explanation_text_from_dict_value(expl_dict[code])
130-
actual = error.__doc__
131-
if actual is None:
141+
expected = _explanation_dict_text_for_cleaned_doc_compare(expl_dict[code])
142+
raw_doc = error.__doc__
143+
if raw_doc is None:
132144
continue
145+
actual = clean_enum_member_docstring(raw_doc)
133146
if expected != actual:
134147
mismatches.append((error, expected, actual))
135148

136149
if not mismatches:
137150
return
138151

139152
lines = [
140-
f"{len(mismatches)} enum member(s) where dict text != __doc__ (strict equality):",
153+
f"{len(mismatches)} enum member(s) where normalized dict text != clean_enum_member_docstring(__doc__):",
141154
]
142155
for error, expected, actual in mismatches[:15]:
143156
lines.append(f" {error!r}")
144-
lines.append(" dict:")
157+
lines.append(" dict (normalized for compare):")
145158
lines.extend(" | " + ln for ln in textwrap.wrap(repr(expected), width=100) or [""])
146-
lines.append(" __doc__:")
159+
lines.append(" cleaned __doc__:")
147160
lines.extend(" | " + ln for ln in textwrap.wrap(repr(actual), width=100) or [""])
148161
if len(mismatches) > 15:
149162
lines.append(f" ... and {len(mismatches) - 15} more")

0 commit comments

Comments
 (0)