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

DOC: Clarify recommendations regarding use of backticks #525

Merged
merged 7 commits into from
Jun 3, 2024
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 35 additions & 16 deletions doc/format.rst
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,9 @@ respective types.
y
Description of parameter `y` (with type not specified).

Enclose variables in single backticks. The colon must be preceded
by a space, or omitted if the type is absent.
The colon must be preceded by a space, or omitted if the type is absent.
When referring to a parameter in the description field or elsewhere within
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this would be simpler as "referring to any parameter of the function being documented", or something along that vein?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So basically remove "in the description field or...". That's probably fine. I think I wanted to point out specifically that this advice was not limited to references within the parameter documentation, but maybe it's better overall to just keep it simple.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd vote for simple as well, something like:

When referring to a parameter elsewhere in the docstring, enclose its name in single backticks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where else can the variable live? Returns? Class docs, etc.?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand. Is the question about what constitutes a "parameter", where else a parameter might be mentioned, or something else?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another intent of the wording here was to try to clarify that parameters of other functions referred to in the current docstring are not subject to this rule. But I think @rossbar's wording does that implicitly, so I've changed it locally and will push shortly.

the same function or class docstring, enclose its name in single backticks.

For the parameter types, be as precise as possible. Below are a
few examples of parameters and their types.
Expand Down Expand Up @@ -549,6 +550,8 @@ not explicitly imported, `.. plot::` can be used directly if
Documenting classes
-------------------

.. _classdoc:
rossbar marked this conversation as resolved.
Show resolved Hide resolved

Class docstring
```````````````
Use the same sections as outlined above (all except :ref:`Returns <returns>`
Expand All @@ -562,10 +565,12 @@ section, may be used to describe non-method attributes of the class::
Attributes
----------
x : float
The X coordinate.
Description of attribute `x`.
y : float
The Y coordinate.
Description of attribute `y`.

When referring to an attribute in the description field or elsewhere within
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The recommendations for methods/attributes are tricky - this is actually not something that numpydoc handles directly. The :meth: and :attr: are roles are built-in to sphinx itself. The fact that putting method and attribute names in single backticks references the relevant doc is a consequence of the sphinx default_role (which I believe is :py:obj: if not explicitly configured), which handles cross-references without any specific type information.

However, there are many cases where this would not be recommended - i.e. if a project uses something other than :py:obj: as the default role, then the cross-referencing may not work as expected leading broken links and nitpick warnings from sphinx. More likely, if a method or attribute does not have its own doc stub (i.e. it's excluded from the relevant autosummary directive), then this will also result in broken links.

In other words, I don't think this is a recommendation that numpydoc should be making. While it is generally good advice (for a standard sphinx configuration) it's not strictly handled by numpydoc thus not really part of the docstring standard, rather more general sphinx/rst advice. My vote would be to exclude these two recommendations, or link to relevant external sphinx docs to explain when wrapping Python objects in single backticks makes sense.

Copy link
Contributor Author

@mdhaber mdhaber Jan 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I would prefer not to remove these entirely.

Is it within numpydoc's purview to recommend that these be rendered as links?

If so, do I understand correctly that typical options will be 1) just single backticks, 2) single backticks preceded by :attr:, or 3) single backticks preceded by some other role, and that the choice is up to the project?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The single-backquote-around-a-parameter concept is part of the original numpydoc specification, though, so I'm not sure we can steer clear of it.

Not sure what to say about projects that reconfigure the default role. Technically, their docstrings are no longer numpydoc compliant, but it's not a big deal as long as they consistently use whichever roles they do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @stefanv for bringing this up again.

@rossbar can you suggest a compromise here? I think we need to address methods and attributes in some capacity. What can we say about them?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The single-backquote-around-a-parameter concept is part of the original numpydoc specification, though, so I'm not sure we can steer clear of it.

Yes, but this is only for the function parameters - recommending that class attributes and methods also be wrapped in single backticks relates to sphinx, not numpydoc, and is nowhere currently mentioned in the numpydoc standard. Generally speaking it's a fine thing to recommend, and if this were a sphinx tutorial I would be +1 for adding it - I'm only leery because this document "defines" the numpydoc docstring standard, and as written this would likely introduce more broken links in documentation (nor does it relate to the "function parameters should be in single backticks" recommendation that has been around since the beginning).

Not sure what to say about projects that reconfigure the default role. Technically, their docstrings are no longer numpydoc compliant

That's not strictly true - the numpydoc standard doesn't prescribe how projects configure the default_role and there are certainly cases where projects may want to override it. To make matters even more confusing, the default_role configuration value can be overridden with the .. default-role:: directive on a per-file basis. The only place where there's currently a collision is the long-standing "function parameters should be in single backticks" recommendation. Currently, numpydoc recommends this but does not implement anything specific for it, so the rendered docs end up using the default_role. The real solution here is to fix this in numpydoc - see #484.

can you suggest a compromise here? I think we need to address methods and attributes in some capacity. What can we say about them?

Since this is generally good advice, I'd be perfectly happy to put it in with softer wording; i.e. something that is very clearly a suggestion and not a necessary part of docstring formatting. Perhaps a less wordy version of:

When combined with `sphinx.ext.autodoc` or `sphinx.ext.autosummary`, included
{attributes/methods} become valid link targets and can be referenced elsewhere in the
docstring with single backticks. See <link to autoclass> for details.

This is hopefully clear, concise, and should do the job for ~95% of use-cases in practice. I'd personally be inclined to include a footnote after "single backticks" to add an additional note about the default role, e.g.

docstring with single backticks[^1]. See <link to autoclass> for details.

[^1]: Depending on the configuration of the `default_role <link to default role>`_ for your project.

but it's not necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 My expectation is only for backticks, anywhere in the docstring, to link to parameter names. It looks like we are in agreement on that, and I'm fine with whatever else is added as Sphinx guidance.

Copy link
Contributor Author

@mdhaber mdhaber Feb 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"function parameters should be in single backticks"

Is that documented, though? I see "Enclose variables in single backticks" (emphasis mine). That is in the Parameters section, but I thought that if "variables" were limited to "function parameters" it would say so. The ambiguity there is what led me to try to clarify.

See <link to autoclass> for details.

Is this what you have in mind?
https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#directive-autoclass

Depending on the configuration of the ``default_role <link to default role>``_ for your project.

This?
https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-default_role

Why does numpydoc make a recommendation about single backticks around parameters if it doesn't do anything with them? Has the intent always been that eventually they would link as you do in gh-484; it just hasn't happened yet?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My best guess is that the intent was to state "function parameters", but 2008 is a long time ago.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does numpydoc make a recommendation about single backticks around parameters if it doesn't do anything with them?

Yeah this is likely an accident of fate - single backticks has always changed the formatting in the rendered docs (even if it was only to the formatting of broken rst links)

the same class docstring, enclose its name in single backticks.
Attributes that are properties and have their own docstrings can be
simply listed by name::

Expand Down Expand Up @@ -606,6 +611,8 @@ becomes useful to have an additional **Methods** section:

"""

When referring to a method in the description field or elsewhere within
the same class docstring, enclose its name in single backticks.
If it is necessary to explain a private method (use with care!), it can
be referred to in the :ref:`Extended Summary <extended_summary>` or the
:ref:`Notes <notes>` section.
Expand Down Expand Up @@ -690,11 +697,11 @@ belong in docstrings.
Other points to keep in mind
----------------------------
* Equations : as discussed in the :ref:`Notes <notes>` section above, LaTeX
formatting should be kept to a minimum. Often it's possible to show equations as
Python code or pseudo-code instead, which is much more readable in a
terminal. For inline display use double backticks (like ``y = np.sin(x)``).
For display with blank lines above and below, use a double colon and indent
the code, like::
formatting should be kept to a minimum. Often it's possible to show
equations as Python code or pseudo-code instead, which is much more readable
in a terminal. For inline display of code use double backticks,
like ````y = np.sin(x)````. For display with blank lines above and below,
rossbar marked this conversation as resolved.
Show resolved Hide resolved
use a double colon and indent the code, like::

end of previous sentence::

Expand All @@ -717,7 +724,9 @@ Other points to keep in mind
(i.e. scalar types, sequence types), those arguments can be documented
with type `array_like`.

* Links : If you need to include hyperlinks in your docstring, note that
* Links : Sphinx will automatically create hyperlinks to module, function,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this recommended practice? I think most libraries use :pyfunc: etc. Genuinely asking, I don't know.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's what is done in SciPy, I think. I think Sphinx only needs more information if there is a name collision.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I think this reaches beyond what numpydoc would recommend (see above). The original information here about name collisions is relevant

Is this recommended practice?

I think it's a tradeoff. With the standard configuration default_role = "py:obj:", using single backticks is equivalent to writing `:py:obj:`target`, which will attempt to link against most things (func, ref, meth, attr, etc.). The primary motivation for excluding the explicit roles is docstring readability in the terminal. However there's nothing to say that you can't or shouldn't use the explicit roles - that's perfectly valid and is up to the library to decide.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine with me to add something about this being a project specific thing and mention the more explicit options, but if it is very common for projects to use single backticks, I think something should be mentioned. What can we say without over-stepping numpydoc's role?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add the common footnote about default role.

mdhaber marked this conversation as resolved.
Show resolved Hide resolved
and class documentation if a recognized name is included within single
backticks (e.g. `numpy`). If you need to include other hyperlinks, note that
Copy link
Contributor Author

@mdhaber mdhaber Jan 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
backticks (e.g. `numpy`). If you need to include other hyperlinks, note that
backticks (e.g. ```numpy``` renders as `numpy`). If you need to include other hyperlinks, note that

But it is not rendering correctly right now.

some docstring sections are not parsed as standard reST, and in these
sections, numpydoc may become confused by hyperlink targets such as::

Expand All @@ -729,17 +738,27 @@ Other points to keep in mind

`Example <http://www.example.com>`_


Common reST concepts
--------------------
For paragraphs, indentation is significant and indicates indentation in the
output. New paragraphs are marked with a blank line.

Use ``*italics*``, ``**bold**`` and ````monospace```` if needed in any
explanations
(but not for variable names and doctest code or multi-line code).
Variable, module, function, and class names should be written between
single back-ticks (```numpy```).
Use ``*italics*``, ``**bold**`` if needed in any explanations.

Use of backticks in reST is a common point of confusion because it is different
from markdown:

- Module, function, and class names should be enclosed within ```single
backticks```. These are intended to render as hyperlinks (e.g. `numpy`). If
the hyperlinks do not render as intended, [insert reference to documentation
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where should users be referred?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestions on that to include here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me, the important distinction to make is: double-backticks is for monospace/code literals, single backticks are for references. If you want to attempt to link to something, use single backticks. If you just want monospace formatting without an attempted link, use double-backticks (the exception of course being numpydoc parameters).

here].
- References to parameters, attributes, and methods defined within the same
docstring should be enclosed within ```single backticks```. These are
currently rendered in *italics*, but there are plans to render a
``monospaced`` hyperlink to the relevant definition in a future version of
numpydoc.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this should be removed, but I wanted to mention it because it is the only reason I can see for using single backticks instead of double backticks. Otherwise, use of single backticks only causes problems with name collisions and renders in italics (which usually means "emphasis") where monospace (which means code) would be more clear.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd just remove this - it's probably more detail than most users are interested in (and is not necessarily correct - the actual rendering of e.g. italics is actually dictated by the sphinx theme).

- All other text that is intended to render in ``monospaced`` font should be
enclosed within ````double backticks````.

A more extensive example of reST markup can be found in `this example
document <http://docutils.sourceforge.net/docs/user/rst/demo.txt>`_;
Expand Down