Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs: make it easier to reference and markup decorators #105812

Open
erlend-aasland opened this issue Jun 15, 2023 · 5 comments
Open

Docs: make it easier to reference and markup decorators #105812

erlend-aasland opened this issue Jun 15, 2023 · 5 comments
Labels
docs Documentation in the Doc dir type-feature A feature request or enhancement

Comments

@erlend-aasland
Copy link
Contributor

erlend-aasland commented Jun 15, 2023

Originally posted by @erlend-aasland in #105792 (comment)

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.

Linked PRs

@erlend-aasland
Copy link
Contributor Author

app.add_directive_to_domain('py', 'decorator', PyDecoratorFunction)
app.add_directive_to_domain('py', 'decoratormethod', PyDecoratorMethod)

class PyDecoratorFunction(PyDecoratorMixin, PyFunction):
def run(self):
# a decorator function is a function after all
self.name = 'py:function'
return PyFunction.run(self)
# TODO: Use sphinx.domains.python.PyDecoratorMethod when possible
class PyDecoratorMethod(PyDecoratorMixin, PyMethod):
def run(self):
self.name = 'py:method'
return PyMethod.run(self)

@AlexWaygood
Copy link
Member

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?

@CAM-Gerlach
Copy link
Member

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
Copy link
Contributor Author

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?

I agree. Explicit is better than implicit.

@erlend-aasland erlend-aasland added type-feature A feature request or enhancement docs Documentation in the Doc dir labels Jun 15, 2023
@CAM-Gerlach
Copy link
Member

CAM-Gerlach commented 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, 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Documentation in the Doc dir type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

3 participants