pytest icon indicating copy to clipboard operation
pytest copied to clipboard

WIP: doc: support sphinx 4

Open bluetech opened this issue 2 years ago • 7 comments

Sphinx 4 (or releases since) provides two nice things (see changelog):

  • It supports "canonical" names for types. I'm not sure exactly what it is, but makes a lot more internal type annotations references resolve in the API Reference. Previously sphinx was confused by the pytest.* reexports from _pytest.
  • python_use_unqualified_type_names config which makes the API Reference signatures a little less noisy.

bluetech avatar Oct 29 '21 09:10 bluetech

Hmm just noticed a regression of sorts - now sphinx shows a bunch of private constructors (e.g. here - search for _ispytest in the API Reference) where previously it didn't. I tried to find a way to hide them again but couldn't find any. (BTW: the problem already exists in fixture functions, where the fixture function parameters are shown, even though they're internal details we really ought to hide).

I'll need to see about that.

bluetech avatar Oct 29 '21 09:10 bluetech

@bluetech

Hmm just noticed a regression of sorts - now sphinx shows a bunch of private constructors (e.g. here - search for _ispytest in the API Reference) where previously it didn't.

That's because Sphinx added new flag for rendering typehints which is set to "all", so suddenly all arguments start to be documented :-D Setting it to autodoc_typehints_description_target = "documented" and explicitly stating what init parameters are documented in the class docstring should help. Example: this diff

--- a/doc/en/conf.py
+++ b/doc/en/conf.py
@@ -38,6 +38,7 @@ release = ".".join(version.split(".")[:2])
 
 autodoc_member_order = "bysource"
 autodoc_typehints = "description"
+autodoc_typehints_description_target = "documented"
 todo_include_todos = 1
 
 latex_engine = "lualatex"
--- a/doc/en/reference/reference.rst
+++ b/doc/en/reference/reference.rst
@@ -347,7 +347,7 @@ Under the hood, the cache plugin uses the simple
 
 ``config.cache`` is an instance of :class:`pytest.Cache`:
 
-.. autoclass:: pytest.Cache()
+.. autoclass:: pytest.Cache(cachedir, config)
    :members:
 
 
--- a/src/_pytest/cacheprovider.py
+++ b/src/_pytest/cacheprovider.py
@@ -55,6 +55,10 @@ Signature: 8a477f597d28d172789f06886806bc55
 @final
 @attr.s(init=False, auto_attribs=True)
 class Cache:
+    """
+    :param Path cachedir:
+    :param Config config:
+    """
     _cachedir: Path = attr.ib(repr=False)
     _config: Config = attr.ib(repr=False)

renders image

hoefling avatar Nov 10 '21 20:11 hoefling

Same is with fixtures, e.g. if I create an incomplete info field list for capsys via

--- a/src/_pytest/capture.py
+++ b/src/_pytest/capture.py
@@ -906,6 +906,9 @@ def capsys(request: SubRequest) -> Generator[CaptureFixture[str], None, None]:
     The captured output is made available via ``capsys.readouterr()`` method
     calls, which return a ``(out, err)`` namedtuple.
     ``out`` and ``err`` will be ``text`` objects.
+
+    :return: an instance of :class:`CaptureFixture[str] <.CaptureFixture>`.
+    :rtype: :class:`CaptureFixture[str] <.CaptureFixture>`
     """
     capman = request.config.pluginmanager.getplugin("capturemanager")
     capture_fixture = CaptureFixture[str](SysCapture, request, _ispytest=True)

(both fields are not needed and set just for demo) renders

image

What's not nice is that the info field list is part of the docstring, so the usage example is shifted down - the example could be moved to the docstring though and placed where desired.

hoefling avatar Nov 10 '21 20:11 hoefling

@hoefling Thanks for looking at this.

Setting it to autodoc_typehints_description_target = "documented" and explicitly stating what init parameters are documented in the class docstring should help.

Seems like we're going to have to do this. It would take some work -- often we omit :param: for "obvious" parameters/short functions.


Another issue with sphinx 4 I noticed is that it now always(?) renders the full signatures of overloaded functions, like pytest.raise and others. These were the reason we switched to autodoc_typehints = "description" in the first place (see #8405) so that's also something we need to fix. Maybe the right solution it to just not use autodoc for those.

bluetech avatar Nov 13 '21 09:11 bluetech

Seems like we're going to have to do this. It would take some work -- often we omit :param: for "obvious" parameters/short functions.

This is something I could tackle, using https://docs.pytest.org/en/stable/ as a reference.

Another issue with sphinx 4 I noticed is that it now always(?) renders the full signatures of overloaded functions, like pytest.raise and others. These were the reason we switched to autodoc_typehints = "description" in the first place (see #8405) so that's also something we need to fix. Maybe the right solution it to just not use autodoc for those.

I think this is an issue with Sphinx 3 as well, only that Sphinx 4 now also includes full qualnames for TypeVars, making a Type[_pytest.python_api.E] out of Type[_E]. I will see what I can dig out, ~~I think aliasing types in Sphinx conf should mitigate that already.~~ nope, requires code modifications for that

hoefling avatar Nov 16 '21 14:11 hoefling

Hmm Sphinx 3 no longer works in Python 3.10 (from types import Union) so this becomes more urgent -- I should get back to this.

bluetech avatar Jan 09 '22 21:01 bluetech

@bluetech Anything I can help to get this in? Archlinux has updated to Python 3.10 in December, and having to edit tox.ini every time I work on the docs is somewhat cumbersome...

The-Compiler avatar Mar 08 '22 17:03 The-Compiler

I updated the PR. Changes:

  • Now requiring Sphinx 5 instead of 4. I set the bounds to >=5, <6. Lower bound because I probably relied on something new, and upper bound to avoid possible breaking changes in Sphinx.
  • I fixed the private __init__ problem discussed above by setting autodoc_typehints_description_target = "documented" and painfully documenting all params. I went over all of the API reference and think it's OK, probably an improvement actually.
  • I fixed the overloads problem with some hack to fool Sphinx (see commit).

So I think this is good to merge.

bluetech avatar Aug 13 '22 18:08 bluetech

Thanks for the review @nicoddemus.

bluetech avatar Aug 13 '22 19:08 bluetech