aio-libs / aiohttp

Asynchronous HTTP client/server framework for asyncio and Python
https://docs.aiohttp.org
Other
15.12k stars 2.02k forks source link

Can't make intersphinx work #3714

Open crusaderky opened 5 years ago

crusaderky commented 5 years ago

In my conf.py I have:

extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.autosummary',
    'sphinx.ext.intersphinx',
    'sphinx.ext.extlinks',
]

# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {
    'python': ('https://docs.python.org/3/', None),
    'aiohttp': ('https://aiohttp.readthedocs.io/en/stable/', None),
}

code.rst:

.. automodule:: code
    :members:
    :undoc-members:
    :show-inheritance:

code.py:

from aiohttp.web import Response, WebSocketResponse, HTTPNotFound

class MyResponse(Response):
    pass

class MyWS(WebSocketResponse):
    pass

def f():
    ":raises aiohttp.web.HTTPNotFound: whoops"
    raise HTTPNotFound()

When I build sphinx, I get:

> [...]
> loading intersphinx inventory from https://aiohttp.readthedocs.io/en/stable/objects.inv...
> [...]
> code.py:code.MyResponse:1: WARNING: py:class reference target not found: aiohttp.web_response.Response                    
> code.py:code.MyWS:1: WARNING: py:class reference target not found: aiohttp.web_ws.WebSocketResponse
> code.py:docstring of code.f:: WARNING: py:exc reference target not found: aiohttp.web.HTTPNotFound

Intersphinx works fine for all other modules in the project. I'm running Python 3.7, Sphinx 2.0.1, and aiohttp 3.5.4.

crusaderky commented 5 years ago

Changing the docstring to

    ":raises aiohttp.web_exceptions.HTTPNotFound: whoops"

does not fix the problem.

asvetlov commented 5 years ago

That's strange because other libraries use aiohttp inventory file without any problem. See https://aiohttp-session.readthedocs.io/en/stable/ for example: it has a link to aiohttp.web.Application in the root document.

webknjaz commented 5 years ago

@crusaderky Apparently, module refs aren't built for the stable branch, only for the latest. So just use it instead.

$ python -m sphinx.ext.intersphinx https://docs.aiohttp.org/en/latest/objects.inv | grep aiohttp.web.HTTPNotFound
        aiohttp.web.HTTPNotFound                 web_exceptions.html#aiohttp.web.HTTPNotFound

$ python -m sphinx.ext.intersphinx https://docs.aiohttp.org/en/stable/objects.inv | grep aiohttp.web.HTTPNotFound
crusaderky commented 5 years ago

@webknjaz Thanks, the workaround fixes the exceptions; however it does not help for the errors about inheritance documentation generated by :show-inheritance:

webknjaz commented 5 years ago

I don't see any of those in the log you've submitted.

crusaderky commented 5 years ago

@webknjaz I'm referring to these two messages:

code.py:code.MyResponse:1: WARNING: py:class reference target not found: aiohttp.web_response.Response
code.py:code.MyWS:1: WARNING: py:class reference target not found: aiohttp.web_ws.WebSocketResponse
webknjaz commented 5 years ago

You can use this command to identify which references exist:

$ python -m sphinx.ext.intersphinx https://docs.aiohttp.org/en/latest/objects.inv | grep aiohttp.web.Response
        aiohttp.web.Response.body                web_reference.html#aiohttp.web.Response.body
        aiohttp.web.Response.text                web_reference.html#aiohttp.web.Response.text
        aiohttp.web.Response                     web_reference.html#aiohttp.web.Response

$ python -m sphinx.ext.intersphinx https://docs.aiohttp.org/en/latest/objects.inv | grep aiohttp.web_response.Response
crusaderky commented 5 years ago

@webknjaz Yes I know - but please see my code.py above. I never refer to aiohttp.web_response.Response explicitly. Sphinx does that by itself when trying to document the parent class because I gave it the :show-inheritance: directive.

asvetlov commented 5 years ago

IMHO sphinx has no inheritance information directive for python domain. Am I wrong?

webknjaz commented 5 years ago

Yep, sphinx only documents what you let it document.

Apparently, we don't generate the complete module index: https://docs.aiohttp.org/en/latest/py-modindex.html / https://docs.aiohttp.org/en/stable/py-modindex.html.

It is possible to make sphinx generate that though and it'd look like https://docs.octomachinery.dev/en/latest/py-modindex.html.

webknjaz commented 5 years ago

:show-inheritance: is supported by Sphinx: http://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html.

The problem is not inheritance (Sphinx has determined that from code.py). The problem is that the class sphinx tries to link against doesn't have it's own reference/page in aiohttp docs.

crusaderky commented 5 years ago

I'm failing to reproduce the problem in my test project:

public.py:

__all__ = ('C', )
from .impl import C

impl.py:

class C:
    pass
$ python -m sphinx.ext.intersphinx build/html/objects.inv
        mymodule.public.C                   apidoc/mymodule.public.html#mymodule.public.C
        mymodule.impl.C                     apidoc/mymodule.impl.html#mymodule.impl.C

I can't figure out why instead in the aiohttp objects.inv I only get the public version.

webknjaz commented 5 years ago

It's because you autogenerate docs for all modules.

crusaderky commented 5 years ago

I found an alternative that doesn't require polluting the index with private objects:

public.py:

__all__ = ('C', )
from .impl import C
C.__module__ = 'mymodule.public'
crusaderky commented 5 years ago

Adding the below to conf.py successfully works around the issue. IMHO it should be placed in the public modules of aiohttp instead.

import aiohttp.web
aiohttp.web.Response.__module__ = 'aiohttp.web'
aiohttp.web.WebSocketResponse.__module__ = 'aiohttp.web'
webknjaz commented 5 years ago

Yeah, I think it's a good idea to enable autodocs on more things just so it'd be possible to reference them.