Skip to content

Commit 86e9488

Browse files
committed
cuda_bindings: add clean_enum_member_docstring helper in enum explanation tests
Introduce clean_enum_member_docstring() for turning FastEnum CUresult / cudaError_t __doc__ strings into plain text: collapse whitespace (newlines to spaces), strip ends, and best-effort strip common Sphinx inline roles (:py:obj:, :py:func:, :obj:, etc.) plus simple ** / * markup. Placed in test_enum_explanations.py for now pending reuse from cuda_core. Add parametrized examples and a None-input test. Made-with: Cursor
1 parent 76efdf6 commit 86e9488

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

cuda_bindings/tests/test_enum_explanations.py

Lines changed: 56 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 re
67
import textwrap
78

89
import pytest
@@ -34,6 +35,61 @@ def _explanation_text_from_dict_value(value):
3435
return value
3536

3637

38+
def clean_enum_member_docstring(doc: str | None) -> str | None:
39+
"""Turn a FastEnum member ``__doc__`` into plain text for display or fallback logic.
40+
41+
Always: collapse all whitespace (including newlines) to single spaces and strip ends.
42+
43+
Best-effort: remove common Sphinx/reST inline markup seen in generated CUDA docs,
44+
e.g. ``:py:obj:`~.cudaGetLastError()` `` -> ``cudaGetLastError()`` (relative ``~.`` is
45+
dropped). Does not aim for perfect reST parsing—only patterns that appear on these
46+
enums in practice.
47+
48+
Returns ``None`` if ``doc`` is ``None``; otherwise returns a non-empty or empty str.
49+
"""
50+
if doc is None:
51+
return None
52+
s = doc
53+
# Sphinx roles with a single backtick-delimited target (most common on these enums).
54+
# Strip the role and keep the inner text; drop leading ~. used for same-module refs.
55+
s = re.sub(
56+
r":(?:py:)?(?:obj|func|meth|class|mod|data|const|exc):`([^`]+)`",
57+
lambda m: re.sub(r"^~?\.", "", m.group(1)),
58+
s,
59+
)
60+
# Inline emphasis / strong (rare in error blurbs)
61+
s = re.sub(r"\*\*([^*]+)\*\*", r"\1", s)
62+
s = re.sub(r"\*([^*]+)\*", r"\1", s)
63+
# Collapse whitespace (newlines -> spaces) and trim
64+
s = re.sub(r"\s+", " ", s).strip()
65+
return s
66+
67+
68+
@pytest.mark.parametrize(
69+
("raw", "expected"),
70+
[
71+
("a\nb c", "a b c"),
72+
(" x \n ", "x"),
73+
(
74+
"see\n:py:obj:`~.cuInit()` or :py:obj:`cuCtxDestroy()`",
75+
"see cuInit() or cuCtxDestroy()",
76+
),
77+
(
78+
"x :py:func:`~.cudaMalloc()` y",
79+
"x cudaMalloc() y",
80+
),
81+
("**Note:** text", "Note: text"),
82+
("[Deprecated]\n", "[Deprecated]"),
83+
],
84+
)
85+
def test_clean_enum_member_docstring_examples(raw, expected):
86+
assert clean_enum_member_docstring(raw) == expected
87+
88+
89+
def test_clean_enum_member_docstring_none_input():
90+
assert clean_enum_member_docstring(None) is None
91+
92+
3793
@pytest.mark.xfail(
3894
reason=(
3995
"Enum member __doc__ is not byte-identical to explanation dicts in current "

0 commit comments

Comments
 (0)