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

Conversation

mdhaber
Copy link
Contributor

@mdhaber mdhaber commented Jan 14, 2024

The Style guide currently gives the following recommendations about backticks:

In the Parameters section:

Enclose variables in single backticks

In Other points to keep in mind:

For inline display use double backticks

In Common reST concepts:

Variable, module, function, and class names should be written between single back-ticks (numpy).

Contributors (and even maintainers) frequently interpret and/or apply these recommendations inconsistently. This PR attempts to clarify the recommendations to avoid multiple interpretations.

Related issues:

Follow-up work includes:

doc/format.rst Outdated Show resolved Hide resolved
doc/format.rst Outdated Show resolved Hide resolved
doc/format.rst Outdated

- 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).

doc/format.rst Outdated
Comment on lines 760 to 761
``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).

@mdhaber mdhaber requested a review from rossbar January 14, 2024 18:52
@mdhaber mdhaber changed the title Clarify use of backticks DOC: Clarify recommendations regarding use of backticks Jan 14, 2024
Copy link
Contributor

@stefanv stefanv left a comment

Choose a reason for hiding this comment

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

Thanks @mdhaber! This looks good overall; I just have a few naive questions.

doc/format.rst Outdated
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.

doc/format.rst Show resolved Hide resolved
doc/format.rst Outdated
@@ -717,7 +726,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.

doc/format.rst Outdated
* Links : If you need to include hyperlinks in your docstring, note that
* Links : Sphinx will automatically create hyperlinks to module, function,
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.

Copy link
Contributor

@rossbar rossbar left a comment

Choose a reason for hiding this comment

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

Thanks for bringing this up @mdhaber ! There's a lot of nice improvements here, though I think a lot of the recommendations on what to enclose in single backticks are beyond numpydoc's purview and shouldn't necessarily be recommended here.

The linking via single backticks is handled by sphinx proper, not numpydoc, and depends on the configuration and thoroughness of auto-generated stubs for each individual project.

I tend to think of the markup as:

  • double-backticks == monospace formatting with no linking
  • single-backticks == attempted linking

The thing that breaks the above is numpydoc's parameter recommendation, which is what I'd like to fix in #484

doc/format.rst Outdated
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.

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

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

doc/format.rst Show resolved Hide resolved
doc/format.rst Outdated

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)

doc/format.rst Outdated Show resolved Hide resolved
doc/format.rst Outdated
@@ -717,7 +726,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.

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.

Co-authored-by: Ross Barnowski <rossbar@berkeley.edu>
Co-authored-by: Matt Haberland <mhaberla@calpoly.edu>
Copy link
Contributor Author

@mdhaber mdhaber left a comment

Choose a reason for hiding this comment

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

Thanks all. @rossbar can you make suggestions on what we can write in these tricky spots? I'd rather not remove them altogether. The hope here was to make numpydoc's recommendations about backticks usage something that can be read and followed. If numpydoc doesn't have a requirement about something, maybe that's fine, but can we say that explicitly? Given all the misuse and confusion (I can produce dozens of PRs if need be), I think it's worth saying something.

doc/format.rst Outdated
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 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?

doc/format.rst Outdated

When referring to an attribute in the description field or elsewhere within
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?

doc/format.rst Outdated
@@ -717,7 +726,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 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?

doc/format.rst Outdated

- 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.

Suggestions on that to include here?

Copy link
Contributor

@rossbar rossbar left a comment

Choose a reason for hiding this comment

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

FWIW I found this summary from @jnothman over in a related scikit-learn issue very relevant: scikit-learn/scikit-learn#11186 (comment)

@timhoffm
Copy link
Contributor

timhoffm commented May 14, 2024

IMHO, the recommendation for single backticks should be complemented with an explanation. Something like

Single backticks are historically used as a means of highlighting. Sphinx tries to resolve them with the default_role, which in the default configuration results in italics. If you use a different default_role in Sphinx you may need to resort to different ways of highlighting, e.g. double backticks or *param* to prevent unintended links or link errors.

doc/format.rst Show resolved Hide resolved
doc/format.rst Show resolved Hide resolved
doc/format.rst Show resolved Hide resolved
doc/format.rst Outdated Show resolved Hide resolved
@mdhaber mdhaber requested a review from rossbar June 3, 2024 18:00
Copy link
Contributor

@rossbar rossbar left a comment

Choose a reason for hiding this comment

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

Awesome, thanks for all the hard work here @mdhaber . I think the current wording recommendations are spot on. We can follow-up with more detailed "troubleshooting" docs to handle the cases when single-backtick behave differently than what users expect.

@rossbar rossbar merged commit b7c6688 into numpy:main Jun 3, 2024
23 checks passed
@stefanv stefanv added this to the 1.8.0 milestone Jun 3, 2024
@mdhaber
Copy link
Contributor Author

mdhaber commented Jun 10, 2024

@rossbar @Carreau @stefanv something not covered by this PR or pydata/pydata-sphinx-theme#1852 is whether short literals like True and 0 should appear in monospaced font when they refer to code (e.g. "None" refers to code when capitalized within a sentence). For the sake of consistency, I'd like for the style guide to recommend that they be rendered as code (and that means double backticks) both in normal text and in parameter/attribute type descriptions. For example:

axis : ``int``, ``tuple``, or ``None``
   blah blah

Of course, "axis" would appear as axis automatically if the suggestion in pydata/pydata-sphinx-theme#1852 is approved. We probably need control within the descriptions, though. (Unless the theme or something else can make an inference?)

Thoughts?

@stefanv
Copy link
Contributor

stefanv commented Jun 10, 2024

That is probably more consistent, but would require rewriting nearly all docstrings.
/cc @lagru who is working on docstub

@mdhaber
Copy link
Contributor Author

mdhaber commented Jun 10, 2024

Many docstrings don't comply with the recommendations already made in this PR. We decided it's OK because compliance with this style guide is optional and can be improved gradually, right? The intent is to reduce future inconsistency that creeps in when the guideline isn't specified.

@lagru
Copy link

lagru commented Jun 11, 2024

As far as I understand this, this should have no impact on docstub.

@Carreau
Copy link
Contributor

Carreau commented Jun 11, 2024

I don't see any reason why None, True and other constant would not be single backticks as they should be crossrefed by intersphinx (https://docs.python.org/3/library/constants.html#True).

Imho the discussion of wether it should use single or double backticks should only be a semantic one, not a visual style one.

In all case I think we can ask:

  • Can it be replaced by a directive without changes to the content of the backtick?
    • Yes -> Single
    • No -> Double.

For example `True` -> :py:obj:`True`, yep single. `from numpy import sin` -> :?:??:`from numpy import sin` I don't see what we can use -> double.

@mdhaber
Copy link
Contributor Author

mdhaber commented Jun 11, 2024

Ah, single is even better then. I didn't consider that they would link.

@Carreau
Copy link
Contributor

Carreau commented Jun 11, 2024

From a quick test:

Screenshot 2024-06-11 at 14 56 17

Which match my expectation, I guess `0` could link, but as it's a specific value, I see why it does not.

Carreau added a commit to Carreau/numpydoc that referenced this pull request Jun 11, 2024
Add the special case for constant, and try to separate semantic (can
link), to style (monospace, link)

See also numpy#525
@Carreau
Copy link
Contributor

Carreau commented Jun 11, 2024

see #565 for my take on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants