From 774f8cc73809c160ca6f6428a897ff09cb0f08be Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 3 Feb 2025 01:07:38 +0000 Subject: [PATCH] Add the new ``py:deco`` cross-reference role (#13292) --- CHANGES.rst | 3 +++ doc/usage/domains/python.rst | 16 +++++++++++++--- sphinx/domains/python/__init__.py | 24 +++++++++++++++++++++++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 756c4af47..28438131a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -98,6 +98,9 @@ Features added Patch by Bénédikt Tran and Adam Turner. * #13163: Always print the full context when Sphinx encounters an internal error. Patch by Kevin Deldycke and Adam Turner. +* #13105: Introduce the :rst:role:`py:deco` role to cross-reference decorator + functions and methods in the Python domain. + Patch by Adam Turner. Bugs fixed ---------- diff --git a/doc/usage/domains/python.rst b/doc/usage/domains/python.rst index 7d7c4e954..8d47a6e02 100644 --- a/doc/usage/domains/python.rst +++ b/doc/usage/domains/python.rst @@ -562,8 +562,7 @@ The following directives are provided for module and class contents: (as opposed to ``.. py:decorator:: removename(func)``.) - There is no ``py:deco`` role to link to a decorator that is marked up with - this directive; rather, use the :rst:role:`py:func` role. + Refer to a decorator function using the :rst:role:`py:deco` role. .. rst:directive:option:: single-line-parameter-list :type: no value @@ -589,7 +588,7 @@ The following directives are provided for module and class contents: Same as :rst:dir:`py:decorator`, but for decorators that are methods. - Refer to a decorator method using the :rst:role:`py:meth` role. + Refer to a decorator method using the :rst:role:`py:deco` role. .. _annotation expression: https://typing.readthedocs.io/en/latest/spec/annotations.html#type-and-annotation-expressions @@ -769,6 +768,17 @@ a matching identifier is found: automatically by Sphinx if the :confval:`add_function_parentheses` config value is ``True`` (the default). +.. rst:role:: py:deco + + Reference a Python decorator; dotted names may be used. + The rendered output will be prepended with an at-sign (``@``), + for example: ``:py:deco:`removename``` produces :py:deco:`removename`. + + .. py:decorator:: removename + :no-contents-entry: + :no-index-entry: + :no-typesetting: + .. rst:role:: py:data Reference a module-level variable. diff --git a/sphinx/domains/python/__init__.py b/sphinx/domains/python/__init__.py index 992a8dcb7..bed701f4a 100644 --- a/sphinx/domains/python/__init__.py +++ b/sphinx/domains/python/__init__.py @@ -28,7 +28,7 @@ if TYPE_CHECKING: from collections.abc import Iterable, Iterator, Sequence, Set from typing import Any, ClassVar - from docutils.nodes import Element, Node + from docutils.nodes import Element, Node, TextElement from sphinx.addnodes import desc_signature, pending_xref from sphinx.application import Sphinx @@ -592,6 +592,27 @@ class PyXRefRole(XRefRole): return title, target +class _PyDecoXRefRole(PyXRefRole): + def __init__( + self, + fix_parens: bool = False, + lowercase: bool = False, + nodeclass: type[Element] | None = None, + innernodeclass: type[TextElement] | None = None, + warn_dangling: bool = False, + ) -> None: + super().__init__( + fix_parens=True, + lowercase=lowercase, + nodeclass=nodeclass, + innernodeclass=innernodeclass, + warn_dangling=warn_dangling, + ) + + def update_title_and_target(self, title: str, target: str) -> tuple[str, str]: + return f'@{title}', target + + def filter_meta_fields( app: Sphinx, domain: str, objtype: str, content: Element ) -> None: @@ -748,6 +769,7 @@ class PythonDomain(Domain): 'data': PyXRefRole(), 'exc': PyXRefRole(), 'func': PyXRefRole(fix_parens=True), + 'deco': _PyDecoXRefRole(), 'class': PyXRefRole(), 'const': PyXRefRole(), 'attr': PyXRefRole(),