You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Docs: make it easier to reference and markup decorators #105812
It would be nice if we had a "decorator role" that used the Python function/method markup, but instead of adding trailing parens, added a prefixing '@': :decorator:`dataclasses.dataclass` => @dataclasses.dataclass.
There's already decorator and decoratormethod directives for signatures. Perhaps we can exploit these so the :py:meth: and py:func: roles adapt the format according to what directive is used. A role could be a nice supplement, though; sometimes we want to explicitly refer to a decorator as a function or the other way around.
I really like the idea of having a py:deco: role for marking up decorators. There's lots of docs PRs I would have used this on in the past; I think it would be very useful. When discussing decorators, I usually want the @ prefixed before the decorator name, and I usually don't want the () after the decorator name that the py:func: role adds.
I'm not sure how I feel about py:func: and py:meth: having different rendering depending on whether the function/method being linked to is a decorator or not. That feels like it might be somewhat surprising behaviour for people new to it?
A :py:deco: role seems most reasonable to me, as it is most consistent with how other multiple roles that mark up and style objects from a single namespace differently depending on the intended semantics operate, and it would also likely be a lot simpler, more robust and more efficient to implement than trying to monkeypatch the :py:func: and :py:meth: roles. It could also potentially get pulled into upstream Sphinx, if @AA-Turner is interested.
To note, Sphinx provides built-in enhanced versions of those two directives, so we could probably dump the custom overrides and switched to the fuller-featured, standard versions instead. It wouldn't really change anything either way with a :py:deco: role, though, since the lookup is ultimately the same.
I'm not sure how I feel about py:func: and py:meth: having different rendering depending on whether the function/method being linked to is a decorator or not. That feels like it might be somewhat surprising behaviour for people new to it?
Implementation-wise, it could be as simple as app.add_role_to_domain(domain="py", name="deco", role=sphinx.domains.python.PyXRefRole) if you don't need custom display behavior (e.g. prepending a @, or not appending ()).
If you do want that, you should be able to just subclass PyXRefRole, wrap process_link to prepend a @ to the returned title (for instance), and then just pass your subclassed PyXRefRole instead of the Sphinx one.
Of course, this doesn't actually check that the target is actually a decorator, but neither do the other :py: roles generally warn if their object types don't match (as they are all stored in the same index). You could implement something like that by modifying the custom decorator directive to add/store some sort of indicator metadata or a list of decorators, and then in process_link check against that list and emit a Sphinx warning if it doesn't match, but not required for an initial implementation.
I started updating the documentation to make use of the :py:deco: role.
How should we reference objects such as classmethod, which is documented as a decorator, but is a class at runtime? There are places where it makes sense to use :deco:`classmethod` as classmethod is referenced as a decorator, but others where it is explicitly mentioned as being a type, e.g.:
Activity
erlend-aasland commentedon Jun 15, 2023
cpython/Doc/tools/extensions/pyspecific.py
Lines 713 to 714 in da911a6
cpython/Doc/tools/extensions/pyspecific.py
Lines 345 to 356 in da911a6
AlexWaygood commentedon Jun 15, 2023
I really like the idea of having a
py:deco:role for marking up decorators. There's lots of docs PRs I would have used this on in the past; I think it would be very useful. When discussing decorators, I usually want the@prefixed before the decorator name, and I usually don't want the()after the decorator name that thepy:func:role adds.I'm not sure how I feel about
py:func:andpy:meth:having different rendering depending on whether the function/method being linked to is a decorator or not. That feels like it might be somewhat surprising behaviour for people new to it?CAM-Gerlach commentedon Jun 15, 2023
A
:py:deco:role seems most reasonable to me, as it is most consistent with how other multiple roles that mark up and style objects from a single namespace differently depending on the intended semantics operate, and it would also likely be a lot simpler, more robust and more efficient to implement than trying to monkeypatch the:py:func:and:py:meth:roles. It could also potentially get pulled into upstream Sphinx, if @AA-Turner is interested.To note, Sphinx provides built-in enhanced versions of those two directives, so we could probably dump the custom overrides and switched to the fuller-featured, standard versions instead. It wouldn't really change anything either way with a
:py:deco:role, though, since the lookup is ultimately the same.erlend-aasland commentedon Jun 15, 2023
I agree. Explicit is better than implicit.
CAM-Gerlach commentedon Mar 20, 2024
Implementation-wise, it could be as simple as
app.add_role_to_domain(domain="py", name="deco", role=sphinx.domains.python.PyXRefRole)if you don't need custom display behavior (e.g. prepending a@, or not appending()).If you do want that, you should be able to just subclass
PyXRefRole, wrapprocess_linkto prepend a@to the returnedtitle(for instance), and then just pass your subclassedPyXRefRoleinstead of the Sphinx one.Of course, this doesn't actually check that the target is actually a decorator, but neither do the other
:py:roles generally warn if their object types don't match (as they are all stored in the same index). You could implement something like that by modifying the custom decorator directive to add/store some sort of indicator metadata or a list of decorators, and then inprocess_linkcheck against that list and emit a Sphinx warning if it doesn't match, but not required for an initial implementation.pythongh-105812: [PoC] add :deco: role and adapt some rst files
:py:deco:role in documentation #131426 as a duplicate of this issueViicos commentedon Mar 18, 2025
I started updating the documentation to make use of the
:py:deco:role.How should we reference objects such as
classmethod, which is documented as a decorator, but is a class at runtime? There are places where it makes sense to use:deco:`classmethod`asclassmethodis referenced as a decorator, but others where it is explicitly mentioned as being a type, e.g.:cpython/Doc/library/abc.rst
Lines 248 to 249 in f819900
In this case, I'd say we could use
:deco:`classmethod <classmethod>`, so that it renders asclassmethod?Similarly, how should
@dataclassbe referenced here?cpython/Doc/howto/enum.rst
Lines 486 to 504 in f819900
Viicos commentedon Apr 17, 2025
@AA-Turner, any reason this was closed? #131426 was closed pointing to this one as the tracking issue.
AA-Turner commentedon Apr 17, 2025
I didn't see any open PRs linking to this, and the main work seemed done.
A
Viicos commentedon Apr 17, 2025
I have pending work locally, but wanted to get feedback on #105812 (comment) before continuing.
3 remaining items
Viicos commentedon Oct 5, 2025
#139598 replaces some occurrences. To be checked still:
contextmanagerasynccontextmanagerdataclassproperty.getter/setterfunctools.total_orderingfunctools.singledispatchfunctools.wrapsreprlib.recursive_reprtestmodule (most likely not a lot of references)typing.runtime_checkabletyping.dataclass_transformtyping.overloadtyping.finaltyping.no_type_checktyping.no_type_check_decoratortyping.overridetyping.type_check_onlyunittest.skipunittest.skipIfunittest.skipUnlessunittest.expectedFailurewarnings.deprecatedEdit: all migrated in this PR.
gh-105812: Use the ``:deco:`` role in place of manual decorator markup (
[3.13] pythongh-105812: Use the ``:deco:`` role in place of manual de…
[3.14] pythongh-105812: Use the ``:deco:`` role in place of manual de…
[3.13] gh-105812: Use the ``:deco:`` role in place of manual decorato…
pythongh-105812: Use the ``:deco:`` role in place of manual decorator…
[3.14] gh-105812: Use the ``:deco:`` role in place of manual decorato…
pythongh-105812: Make use of the Sphinx `deco` role in documentation,…
pythongh-105812: Make use of the Sphinx `deco` role in documentation,…
gh-105812: Make use of the Sphinx `deco` role in documentation (#139598)
pythongh-105812: Make use of the Sphinx `deco` role in documentation (p…
[3.15] gh-105812: Make use of the Sphinx `deco` role in documentation (…
[3.14] gh-105812: Make use of the Sphinx `deco` role in documentation (…
[3.13] gh-105812: Make use of the Sphinx `deco` role in documentation (…