Confused by warnings from Doc/library/fcntl.rst

I went looking for another documentation file to clean up (reference-wise: see gh-101100) and chose Doc/library/fcntl.rst. I ran sphinx-build with the necessary options to get it to report nitpicky problems. The start of the output was:

.../Doc/library/fcntl.rst:16: WARNING: c:func reference target not found: ioctl
.../Doc/library/fcntl.rst:142: WARNING: c:func reference target not found: ioctl
.../Doc/library/fcntl.rst:167: WARNING: c:func reference target not found: flock

Considering just the first warning, line 16 begins this paragraph:

This module performs file control and I/O control on file descriptors. It is an
interface to the :c:func:`fcntl` and :c:func:`ioctl` Unix routines.  For a
complete description of these calls, see :manpage:`fcntl(2)` and
:manpage:`ioctl(2)` Unix manual pages.

Later in the file, both fcntl and ioctl are described in dedicated sections:

.. function:: fcntl(fd, cmd, arg=0)
   ...

.. function:: ioctl(fd, request, arg=0, mutate_flag=True)
   ...

As far as I can tell, these targets should satisfy the :c:func:... references, right? Why does Sphinx complain about ioctl but not fcntl?

I displayed the rendered HTML. Neither the fcntl nor ioctl references were rendered as hyperlinks. Since Sphinx didn’t complain about fcntl I figured it should be displayed with a hyperlink. Both of the :manpage: items later in the first paragraph were rendered as hyperlinks into the online Debian man pages, so I know something was working as I expected.

What the heck am I missing here?

Note the c:func part. These references are meant to reference the C functions ioctl and flock, not the corresponding Python functions.

I don’t know if there is a good place to link for the C functions (maybe the C standard?), so perhaps the best solution is to simply remove the links.

2 Likes

You could also link to the respective POSIX spec pages, though I’m not sure how stable their URIs are.
https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
https://pubs.opengroup.org/onlinepubs/9699919799/functions/ioctl.html

(and for some reason Discourse is not able to preview those pages :slight_smile: )

We can discuss where :c:func:`whatever` should link. I am more immediately concerned that I can’t tell why it complains about one :c:func: directive but not the other. I will suppress such directives which are referring to functions outside of the Python C API.

Aside: Isn’t the :c:func: directive meant to reference a C function within the Python C API? If you want to refer to documentation for system calls or Unix stdlib functions, shouldn’t a different/new directive be used?

Did I accidentally post this to Core Dev or did someone move it from Documentation (where I intended to post it)?

FWIW, I’ve taken the plunge with a new PR.

1 Like

You posted to Core Development, but I’ve just moved it to Documentation. You can see the edit history (including category moves) by clicking image on the top right of the first post.

Yes, and yes.

In theory if there was a Sphinx version of the C standard docs we could intersphinx to that and everything would magically work (the Linux kernel docs use Sphinx, so we could intersphinx to them if they define common APIs there), but some downstreams have expressed concerns about us using Intersphinx for their building their local offline documentation.

Instead, we could link them on first usage if they are important to the text (or include those references as Seealso links, if they aren’t already); otherwise we can continue to do as we’ve been doing and retain the styling/semantics, but simply silence the link resolution either locally (with ! ) or globally (by adding it to nitpick_ignore in conf.py), as I see @smontanaro is familiar with already from his previous PRs.

Might have something to do with them being ancient HTML 4, quirks mode, legacy non-UTF-8 documents…or just lacking the appropriate meta tags.

Because :c:func fcntl has been added to nitpick_ignore in conf.py, but not c:func ioctl. @erlendaasland as the person who added the former and a C-API expert, any idea why that was so? I recall you discussing what to add to nitpick_ignore along with Victor and Serhiy semi-recently, when there was disagreement on how much to add there.

The :c:func: role (and the corresponding c:function:: directive) can be used for any C function, just like any of the other domain directives. They do tend to imply a cross-reference, which is possible either locally or through intersphinx, but for consistency and styling purposes can also be used for other defined, canonically referenced functions (though generally not for functions intentionally don’t exist, like examples). was, (Though AFAIK, that was more or less the original nominal use case a couple decades ago when Sphinx was more or less a set of docutils/reST extensions used by the Python docs).

Theoretically, we could come up with a whole new custom directive to style and link to them, if the URLs are reasonably predictable (or we just hardcode them somewhere), but that would be a non-trivial amount of work and not our highest priority at the moment.

I guess we added the fcntl() system call to nitignore because it was referred to in multiple places in the docs[1]. We could probably add the ioctl() syscall to that list as well.


  1. a quick git grep yields a couple of handfuls of results ↩︎

2 Likes

Thanks @erlendaasland. I can add that change to my PR.

I looked briefly at the Sphinx code thinking it would be straightforward to determine how to create a new role for stuff like C stdlib and system calls. Boy was I wrong. I couldn’t make heads or tails of where that stuff lives. I guess I need to spend some time with the Sphinx docs.

1 Like

Thanks; I went ahead and reviewed it with a few other comments, which besides what we discussed here can all be resolved via applyable or copy/pasted suggestions. I marked the review as blocking to avoid the PR being accidentally merge before you’ve had time to make he indicated changes, as I noticed it was already approved and you’d requested a merge. I’m happy to help take care of this for you via a commit to your branch, if you’d like—just lmk!

Again, speaking from experience as someone who both works a good deal on the CPython docs and who has spent way too much time getting intimately familiar with the complexities of implementing custom directives/roles and the internals of the various Sphinx-provided domains, my earnest advice would be to maybe reconsider sinking more of your valuable time into that rabbit hole:) There’s a lot of other much lower-hanging fruit to focus on first in this department, which in turn (particularly fixing the remaining outstanding warnings) will give us a better idea of the potential need for this, and make it easier to apply if we do go forward with it. And if we did want to implement it, I could help, but the hard parts would still be carefully thinking through and getting consensus on the number of design and implementation decisions it would require.

It’s something that could potentially be nice to have if designed and implemented appropriately, but we’d definitely need to proceed step by step and have a wider discussion on whether we want it and how exactly it would be designed first (since I see a number of possible choices, but its not obvious which if any would make sense from both a conceptual and an implementation perspective). However, to be frank, ISTM that we have much bigger fish to fry at the moment in terms of doc content, organization, presentation and infrastructure that something like that isn’t a high priority at the moment, particularly in light of the non-trivial cost to the complexity/bespoke expertise required budget for doc contributors.