-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Description
Describe the bug
Let's say you have a module:
# mypackage/module.py
class A:
pass
And expose it in your __init__.py
:
from .module import A
__all__ = ["A"]
In your doc, you want to expose the "official" api:
.. autoclass:: mypackage.A
And reference it:
Use the :any:`A` class
Alternatively, in conf.py
use default_role = "any"
and in your doc:
Use the `A` class
Then autodoc will output an warning:
more than one target found for 'any' cross-reference 'A': could be :py:class:`mypackage.A` or :py:class:`myackage.module.A`
And if building with -W
, this warning will be an error.
I believe there's no way to avoid this warning without abandoning :any:
altogether.
How to Reproduce
$ git clone git@github.com:ewjoachim/sphinx-bug-any-canonical.git
$ cd sphinx-bug-any-canonical
$ pip install -r requirements.txt
$ cd docs
$ make SPHINX_OPTS=-W html
<build fails>
Expected behavior
There used to be a way for me to simultaneously:
- Use
:any:
- Define the API of my project in
__init__.py
while having the real classes live elsewhere - use
autodoc
- build with
-W
without the combination of those things failing the build. I can probably rewrite a lot of documentation to use explicit py:obj:
classes instead of any but it would be a lot of work, and I'm not sure it would make my doc more readable.
Your project
https://github.com/ewjoachim/sphinx-bug-any-canonical
Screenshots
No response
OS
Linux
Python version
3.8, 3.9, 3.10
Sphinx version
latest stable: 4.3.2
Sphinx extensions
sphinx.ext.autodoc
Extra tools
No response
Additional context
I believe what happens is that:
sphinx/ext/autodoc/__init__.py ClassDocumenter.add_directive_header
we have
canonical_fullname = self.get_canonical_fullname()
if not self.doc_as_attr and canonical_fullname and self.fullname != canonical_fullname:
self.add_line(' :canonical: %s' % canonical_fullname, sourcename)
This means that the py:class directive that will be generated by autodoc will have a :canonical:
option
sphinx/domains/python.py PyObject.add_target_and_index
canonical_name = self.options.get('canonical')
if canonical_name:
domain.note_object(canonical_name, self.objtype, node_id, aliased=True,
location=signode)
If an object has a canonical option, both names will be added to the known objects.
This means that :any:`Class`
will always end up confused, and issue a warning.
I don't know how I can solve this.