Open radarhere opened 3 weeks ago
I'm making an educated guess that something goes wrong when you try to display the inheritance because that implies linking to the Python standard library and the error message seems to suggest there's some magic under the hood (as is hinted by the unexpected change from a public io.BytesIO
to a private _io.BytesIO
):
WARNING: py:class reference target not found: _io.BytesIO [ref.class]
Did you try getting rid of :show-inheritance:
to see if it builds?
.. autoclass:: PIL.AppendingTiffWriter
:show-inheritance:
another alternative would be hardcoding the fully qualified name in autodoc, like:
.. autoclass:: PIL.AppendingTiffWriter(io.BytesIO)
Anyway, I checked your intersphinx and it seems alright. When one of these problems happens the surest workaround (generally happens to me with ABCMeta
stuff) is to add the inheritance in conf.py
circumventing the resolution step by using autodoc-process-bases
, something like:
def add_superclass(app, name, obj, options, bases):
"""Used to add a superclass (or metaclass) to the bases of a class."""
from your_module import your_super_class
if name == "your_module.your_subclass":
bases.append(your_super_class)
def setup(app):
app.connect("autodoc-process-bases", add_superclass)
As to what causes these things? Who's to say...?! Your MRE seems alright to me.
Removing :show-inheritance:
does work, but that's not an ideal solution.
but that's not an ideal solution.
I agree. I don't contribute fixes for Sphinx's internals and this issue is beyond my knowledge of the internals. But of the 3 workaround alternatives using the conf.py
autodoc event is generally considered the most reliable - it's what I use when the easier options don't work out.
I didn't mean change the Python code. I meant write the fully qualified name directly into the autodoc declaration parenthesis so that the cross-reference gets resolved without checking the run-time imported AppendingTiffWriter
- exactly like I showed in the 2nd alternative (again these changes are in the .rst
not the .py
).
.. autoclass:: PIL.AppendingTiffWriter(io.BytesIO)
:show-inheritance:
I checked the uncompiled objects.inv
and for BytesIO
and it's:
py:class
io.BytesIO library/io.html#io.BytesIO
So all 3 methods should resolve it.
I didn't mean change the Python code. I meant write the fully qualified name directly into the autodoc declaration parenthesis
You're right, sorry, I misread that.
My own workaround was simply nitpick_ignore = [("py:class", "_io.BytesIO")]
.
But I had imagined that either a) there was something wrong in my code, or b) the situation implied a bug in sphinx or a sphinx-related extension, or perhaps that a workaround should be hardcoded into sphinx-related code itself somewhere to account for a Python oddity.
If the considered opinion of the sphinx community is that this is just how things are though, that's... unexpected, but thanks for your time.
Hi Andrew,
Thank you for writing this up, I agree it is a bug, and I imagine probably because Sphinx is resolving the type at runtime to the builtin _io extension module rather than the public io module. I haven't tested this, though.
The simplest way to resolve this is probably a map of overrides, though ugly. It is interesting that it only manifests with :show-inheritance:, though.
A
@radarhere
to account for a Python oddity.
I guess it's something non standard in Python's io.BytesIO
that autodoc then fails to handle properly.
this is just how things are though, that's... unexpected
I personally prefer the alternatives I've shown but using nitpick_ignore
might be the better choice depending on project/doc layout (for some users changing .rst
might be less intrusive, while others may prefer adapting their conf.py
).
There's an additional problem to using nitpick_ignore = [("py:class", "_io.BytesIO")] because you're silencing other potential problems with _io.Bytes
while adapting an individual autodoc directive solves the linking issue locally.
@AA-Turner
The simplest way to resolve this is probably a map of overrides, though ugly.
If it gets the job done it's better to get an easy interim solution until something more durable is thought of.
I guess it's something non standard in Python's io.BytesIO that autodoc then fails to handle properly.
Actually, _io.BytesIO
is not documented as such but as io.BytesIO
. So intersphinx is trying to find _io.BytesIO
. It could be solved if CPython included an index for _io.BytesIO
but that's not currently the case. The reason why we actually try to find _io.BytesIO
is because the fully-qualified name of BytesIO
is _io.BytesIO
even though the latter is being imported from io
(to be precise, there is an io.py
module which itself imports _io
and re-exports some members. So the declaring module for BytesIO
is _io.BytesIO
but exposed and documented as io.BytesIO
).
I have less time to work on autodoc. I don't know when I'll have time. I had in mind some improvements for autodoc_type_aliases
but it wouldn't be helpful in the context of inheritance.
If I recall correctly, here's the actual flow:
_io.BytesIO
appears.:class:`_io.BytesIO`
in the RST._io.BytesIO
. This reference does not exist.One way to fix it is to pre-process nodes before calling the reference resolver. This can be done by remapping fully-qualified names into names that are known to exist. I had something locally setup for that but I'm not sure it's universal enough. In addition the implementation depends on various other utilities that I implemented so I'm not even sure I can bundle it as a standalone fix.
It could be solved if CPython included an index for _io.BytesIO but that's not currently the case.
This might actually be a CPython problem, googling for the generic error message generally leads to https://bugs.python.org/issue11975 so maybe they should adjust their index for _io.BytesIO
?
Describe the bug
It appears to me that intersphinx is unable to create a link to
BytesIO
when a class inherits from it.How to Reproduce
I've created a minimal reproduction at https://github.com/radarhere/sphinx_demo. The build can be triggered using GitHub Actions. See https://github.com/radarhere/sphinx_demo/actions/runs/10748344237 for full output.
Environment Information
Sphinx extensions
Additional context
No response