-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Python API documentation generation extension #99
Conversation
Note: This still needs some revision, especially the documentation, but I'd welcome feedback. |
Also, will probably want to rename this extension along with many of the others, but I figured I'd wait to do that until #98 is merged to avoid conflicts. |
yeah (thank you) - Refactoring should definitely get a separate PR. |
I still find it offsetting when I click on a class name in a sig and find my self on a nested page. The number 1 reason I love this theme is the hamburger menu. And, when I'm transported to a nested page (for class summary), the hamburger menu isn't exactly showing the correct items. For Example, the class overview for So, I think the global toc is structured strange. Notice after clicking on Sorry for the long post, I'm not sure if I'm finding the right words here. |
Is this demo pre-compiled? I noticed that the tensorstore also uses 0-level indentation for docstrings. FYI, pybind11 will auto-dedent raw doctrings, so you can maintain the same level indentation in the C++ src. I can understand if it was done that way for easy docstring composition (when writing or copy-paste the docs srcs). |
I actually changed how the TOC works compared to in the tensorstore docs. Previously the logic for splitting the toc into a global and local toc was not quite right (see first commit in this PR). Now, when in the "desktop" mode the links to members are in the left-side "global toc" and take you to a different page, while the right-side "local toc" (which contains sections, but also parameter names) takes you to links within the same page. When in the "mobile" / "tablet" mode, though, I agree that the menu is behaving rather weirdly, with it starting out nested deep in a menu for some reason, and the back button moving to the previous sub-menu rather than taking you up a level. I will have to look into what is going on there. |
Yes, the The reason there is no indentation is that the logic for parsing pybind11 overloaded function signatures expects the precise formatting used by pybind11 and does not work if the docstring is indented as is customary in Python code. I think it should work if the individual docstrings specified to pybind11 in the C++ code are indented, since as you say pybind11 will dedent them, and additionally, the additional syntax used by pybind11 to indicate overloaded functions would not be indented in any case. The reason the tensorstore C++ code uses no indentation in its docstrings is unrelated:
|
@jbms this is amazing!! ❤️ 🎉 This is the feature I've been dreaming of since I saw your PR in the sphinx-material repo and discovered your Tensorstore. I thought I'd test this on my library and provide feedback. When trying to use the new But before sharing that, I discovered another issue. Using this branch without adding the I built the latest from my library using these two adjacent commits. 55a6bb7f2d5349 |
This isn't the first time we've encountered regressions to conf.py usage. We could try using pytest with tox to run tests... Note sure what the best way to verify the test output is - I think sphinx-design uses pseudo XML comparison. |
Regarding the modified TOC, here are my two cents (if they're worth anything). I find all the class methods and attributes in the left side TOC a little confusing and cluttered. The left-side TOC is already displaying so much and to put all the sub-contents on the left as well seems, to me, to be a bit much. The right-side TOC doesn't really have a purpose anymore (for API documentation). Perhaps both the left and right TOC can contain the contents, but the left-side TOC is not expanded by default? See below. Current classExpected/desired class (made in paint)And then when you click on a method or property, it takes you to that page, but you can still see where you are in the hierarchy on the left. (The below screenshot is the current and desired behavior. No change requested.) |
@mhostetter It would be difficult to please that request because you seem to want right side toc used for all but the deepest level. If I'm understanding the mock results and desired behavior, then the entities would end up duplicated for different locations/levels of the TOCs. This could be a preference thing also. I kinda like the current intention - just need to fix the unexpected nesting. It would be cool if the right side ToC is auto-hidden for pages with no local ToC to show; maybe it does that and I missed it - in any case, that'd be a separate issue. |
Thanks @mhostetter and @2bndy5 for your feedback. I have struggled to figure out the best behavior for the TOC. Originally when first designing this functionality for tensorstore my vision was exactly as @mhostetter described, with the right-side TOC serving as a "class outline". The way this theme worked prior to the "Fix separation of local and global tocs" commit in this PR, is that the branch of the global TOC corresponding to the current page is simply cut off and moved to the right side (and then pruned so that it doesn't include multiple levels of headings from other pages). When paired with the python_apigen extension, that does result in the right-side TOC containing a "class outline" when on the page that documents a class. However, there are two downsides to this approach:
In the tensorstore docs, I tried to mitigate the second issue by using a special option on the API documentation pages for classes to duplicate the contents of the local TOC on the left side as well (rather than cutting it out). That allows you to continue to drill down on the left side without having to switch back and forth between the left and right side, while preserving the "class outline" on the right side. But it does not solve the first issue, and also duplicating the TOC doesn't seem very elegant. Potentially some of the issues could be mitigated by the solutions outlined in #58. Collapsing by default certain parts of the left side TOC is also an interesting option, but I am worried it would also make it less convenient to "drill down" multiple levels using the left side TOC. With the current design in this PR, I agree that the right side TOC is not too useful for most classes, since it just contains the section headings (which are also in the left side TOC). For functions it is still useful since it shows parameters: As far as auto-hiding the right-side TOC if it is empty, I think that actually used to be the behavior of upstream mkdocs-material but was changed a while back. I'm not sure what the motivation for that change was, but perhaps it was to ensure a consistent width for the main content regardless of whether there is a TOC, to keep the layout structure more consistent as you navigate between pages. |
I will have to look into why properties are no longer being included in the TOC. |
@jbms The properties are not documented on the page at all, with the exception of the broken autosummary table links.
Here's an idea -- what about prepending a "->" (or some equivalent symbol) before the "M" and "P" colored icons in the right-side TOC to indicate this link is taking you to another page. I imagine this is only useful for API documentation. This is a quick-and-dirty paint example. |
I think material design has an icon specifically for that |
A documentation suggestion: In your usage section of the docs, you have: python_apigen_modules = {
"my_module": "api",
} I would suggest you add that a user should create a page with this, for example: my_module
=========
.. python-apigen::
:fullname: my_module
:objtype: module It wasn't obvious to me how to invoke the API generation. I had to look at the |
Thanks @mhostetter. To be clear, all of the individual documentation pages are generated regardless of that directive, but they are not linked from anywhere else. The directive just inserts a summary of the module. One change I have been considering is to change the directive so that it inserts a summary of a single group rather than the entire module. For example, currently if we have multiple groups can do: .. python-apigen::
:fullname: my_module
:objtype: module
Core
====
This is documentation for core stuff.
Indexing
=========
This is documentation for indexing stuff. Instead, it would become: Core
====
This is documentation for core stuff.
.. python-apigen:: core
Indexing
=========
This is documentation for indexing stuff.
.. python-apigen:: indexing
This would allow you to document entities from multiple different modules together, if they happen to be assigned the same group identifier. This also matches what I've done for the C++ autosummary (not yet made into a PR). |
I like that idea. It gives more control over the presentation of the API. Also @jbms , I determined why the current state of this PR fails to build my docs. It is related to this chunk of code: sphinx-immaterial/sphinx_immaterial/python_apigen.py Lines 676 to 689 in f2d5349
I was able to reproduce the error I get in my docs with this simple The foo module# foo/__init__.py
from ._bar import * # foo/_bar.py
def function_1(arg_1: str, arg_2: int) -> str:
"""
This is a docstring.
"""
return arg_1 * arg_2
class Charlie:
def my_method(self, arg_1: str) -> str:
"""
This is a docstring of a method.
"""
return arg_1
@property
def my_property(self) -> int:
"""
This is a docstring of a property.
"""
return 1
class Delta(Charlie):
@classmethod
def my_classmethod(cls, arg_1: str) -> str:
"""
This is a docstring of a method.
"""
return arg_1 Error output
I believe the error is related to the fact that Thanks again for the PR and taking the time. |
@mhostetter I'm still not sure about the cause of the attributes not displaying ---- when trying to build the documentation for your library, I was getting various unrelated build errors. However, it probably has to do with the changes to autodoc_property_type.py --- you might try adding some additional debugging output there. |
60a3813
to
112bc3f
Compare
@jbms as of today (I noticed some recent force pushes), the properties appear now as they did before and my docs build on this branch without modifying conf.py (i.e., not using When building with Build output
To reproduce, run As always, thanks for your time and effort! |
well it looks like sphinx recently moved to 5.0.1 as latest. I get a completely different error when using v5.0.1 (please note the deprecation warnings):
If I switch back to v4.5.0, then I can reproduce the error reported by @mhostetter , but I also get warnings about duplicate object descriptions:
|
FWIW, @2bndy5 I do not get those duplicate object warnings with Sphinx v4.5.0... |
Previously, if the global toc was empty, the build failed with an error. With this change, an empty TOC is correctly supported.
This JavaScript file is added by the basic theme but is not required by this theme.
This can occur in unit tests.
Oh we can't use |
Actually there was a bug a in I also fixed all of the warnings regarding missing references, and enabled |
Co-authored-by: Brendan <[email protected]>
This adds an independent implementation of the toc.follow feature that is available in mkdocs-material-insiders. Unlike the mkdocs-material feature, this also scrolls the left-side panel to keep the current document/current section within the viewport.
Previously, neither the `toc.integrate` feature, nor the "layered" TOC menu for "tablet portrait" viewports and narrower, worked correctly on non-leaf pages, due to a limitation of the upstream mkdocs-material theme. This commit avoids those limitations except on the root page. Co-authored-by: Brendan <[email protected]>
Co-authored-by: Brendan <[email protected]>
Co-authored-by: Brendan <[email protected]>
The parameter cross-linking feature of this theme results in `py:param` references to parameter descriptions being added automatically to every Python function signature. When `nitpicky = True`, this leads to a warning for every parameter that does not have a description, which is not helpful. This change suppresses those warnings for the implicitly-added `py:param` references.
Previously, the get_mappings method incorrectly returned a temporary dict object on the first call.
Thanks for the review! |
tagged as v0.8.0 |
Fixes #91