Skip to content

Commit 1cbc355

Browse files
committed
sphinx-autodoc-argparse(refactor[typing]): register CLI roles via Sphinx.add_role
why: The five `cli-*` inline roles were registered via `docutils.parsers.rst.roles.register_local_role`, which is typed strictly for docutils-shaped callables and rejects Sphinx-style role functions — each call needed `# type: ignore[arg-type]`. `Sphinx.add_role(name: str, role: Any, override: bool = False)` (`sphinx/application.py:1121`) accepts sphinx-shaped roles cleanly and scopes registration to the Sphinx app rather than mutating docutils process-global state. what: - Change `register_roles() -> None` to `register_roles(app: Sphinx) -> None` - Replace 5 `roles.register_local_role(..., ...) # type: ignore[arg-type]` calls with `app.add_role(...)` — removes 5 ignores - Drop `from docutils.parsers.rst import roles` import - Add `TYPE_CHECKING` import of `sphinx.application.Sphinx` - Expand docstring to explain the scope change; convert the doctest to the standard `>>> register_roles # doctest: +ELLIPSIS` form used elsewhere in the workspace - Update the single caller in `exemplar.py:setup` to pass `app` - Tighten `tests/ext/test_argparse_roles.py::test_register_roles` to verify the five expected role names are registered, using a local `_RoleRecorder` stub cast to `Sphinx`
1 parent c94bc5a commit 1cbc355

3 files changed

Lines changed: 45 additions & 14 deletions

File tree

packages/sphinx-autodoc-argparse/src/sphinx_autodoc_argparse/exemplar.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1364,7 +1364,7 @@ def setup(app: Sphinx) -> SetupDict:
13641364
# Register CLI inline roles for documentation
13651365
from sphinx_autodoc_argparse.roles import register_roles
13661366

1367-
register_roles()
1367+
register_roles(app)
13681368

13691369
return {
13701370
"version": __version__,

packages/sphinx-autodoc-argparse/src/sphinx_autodoc_argparse/roles.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
import typing as t
1717

1818
from docutils import nodes
19-
from docutils.parsers.rst import roles
2019

2120
if t.TYPE_CHECKING:
2221
from docutils.parsers.rst.states import Inliner
22+
from sphinx.application import Sphinx
2323

2424

2525
def normalize_options(options: dict[str, t.Any] | None) -> dict[str, t.Any]:
@@ -348,8 +348,14 @@ def cli_choice_role(
348348
return [node], []
349349

350350

351-
def register_roles() -> None:
352-
"""Register all CLI roles with docutils.
351+
def register_roles(app: Sphinx) -> None:
352+
"""Register all CLI roles with the Sphinx application.
353+
354+
Uses :meth:`sphinx.application.Sphinx.add_role` (Sphinx-scoped)
355+
rather than ``docutils.parsers.rst.roles.register_local_role``
356+
(docutils process-global). The Sphinx accessor is typed as
357+
``(name: str, role: Any, override: bool = False) -> None`` so no
358+
``# type: ignore`` is required.
353359
354360
This function registers the following roles:
355361
- cli-option: For CLI options (--verbose, -h)
@@ -358,13 +364,19 @@ def register_roles() -> None:
358364
- cli-default: For default values (None, "default")
359365
- cli-choice: For choice values (json, yaml)
360366
367+
Parameters
368+
----------
369+
app : Sphinx
370+
The Sphinx application instance. Must be called from within
371+
an extension ``setup(app)`` hook.
372+
361373
Examples
362374
--------
363-
>>> register_roles()
364-
>>> # Roles are now available in docutils RST parsing
375+
>>> register_roles # doctest: +ELLIPSIS
376+
<function register_roles at 0x...>
365377
"""
366-
roles.register_local_role("cli-option", cli_option_role) # type: ignore[arg-type]
367-
roles.register_local_role("cli-metavar", cli_metavar_role) # type: ignore[arg-type]
368-
roles.register_local_role("cli-command", cli_command_role) # type: ignore[arg-type]
369-
roles.register_local_role("cli-default", cli_default_role) # type: ignore[arg-type]
370-
roles.register_local_role("cli-choice", cli_choice_role) # type: ignore[arg-type]
378+
app.add_role("cli-option", cli_option_role)
379+
app.add_role("cli-metavar", cli_metavar_role)
380+
app.add_role("cli-command", cli_command_role)
381+
app.add_role("cli-default", cli_default_role)
382+
app.add_role("cli-choice", cli_choice_role)

tests/ext/test_argparse_roles.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
register_roles,
1818
)
1919

20+
if t.TYPE_CHECKING:
21+
from sphinx.application import Sphinx
22+
2023
# --- normalize_options tests ---
2124

2225

@@ -311,9 +314,25 @@ def test_cli_choice_role(
311314

312315

313316
def test_register_roles() -> None:
314-
"""Test register_roles doesn't raise errors."""
315-
# This should not raise any exceptions
316-
register_roles()
317+
"""register_roles() registers the five CLI roles via app.add_role()."""
318+
319+
class _RoleRecorder:
320+
def __init__(self) -> None:
321+
self.added: list[tuple[str, object]] = []
322+
323+
def add_role(self, name: str, role: object, override: bool = False) -> None:
324+
self.added.append((name, role))
325+
326+
app = _RoleRecorder()
327+
register_roles(t.cast("Sphinx", app))
328+
329+
assert [name for name, _ in app.added] == [
330+
"cli-option",
331+
"cli-metavar",
332+
"cli-command",
333+
"cli-default",
334+
"cli-choice",
335+
]
317336

318337

319338
# --- Role Return Type Tests ---

0 commit comments

Comments
 (0)