Python functions with type hint annotations often have very long signatures. The arguments in these signatures often have internal spaces, so naive line-wrapping produces poor results with lines broken in the middle of an argument instead of between arguments.
For example, see tornado.httpclient.HTTPRequest:

This is kind of a monster no matter what you do with it, but it would be more legible if it were formatted with one parameter per line as in the source code (which is auto-formatted with black, FWIW). Or for less-intrusive changes, consider converting whitespace within an argument to non-breaking spaces (although I occasionally have single arguments whose type annotations span multiple lines), or at least putting a <span> with a designated class around each argument so CSS could perhaps be used for styling the arguments.
+1; Reasonable.
+1; This quickly becomes extremely ugly even for more minimal examples than the one above.
See also #4390.
Fixed by #4390.
Thanks,
Sorry for my wrong. Reopened.
How could we proceed with this issue?
@sotte The introspection module should be able to provide the list of arguments along with their types, this could be used to reformat the whole signature, without relying on the source code formatting. Also, this could allow having options, such as showing the type hints in the signature or not, etc.
The current built-in extension module sphinx.ext.autodoc.typehints allows for the option autodoc_typehints = "description" which will move the type hints from the signature to the description. This seems to still be experimental, but it looks much better.
Yes, I believe sphinx.ext.autodoc.typehints is useful for such complex function. Indeed, it is marked as "experimental". But it only means beta or rc release. I need feedbacks to mature the extension to be merged into autodoc formally.
Anyway, it is still important to give a CSS classes to each element of signatures. So I'll keep working for it. I think #6990 will resolve this.
Now I merged #6990. It allows you to decorate function signatures via CSS more flexibly. But it's not perfect. we need to improve the output more. I need a comment to enhance it more. Does anybody try it and give us comments please?
This looks fantastic! As a preview to any readers, suppose we have a function with the following signature:
def read_config(file: Union[os.PathLike, str] = "config.ini"):
pass
With the conf.py parameter autodoc_typehints = "signature", Sphinx previously would generate the following HTML for the parameter:
<em class="sig-param">file: Union[os.PathLike, str] = 'config.ini'</em>
now, it generates:
<em class="sig-param">
<span class="n">file</span>
<span class="p">:</span>
<span class="n">Union[os.PathLike, str]</span>
<span class="o">=</span>
<span class="default_value">‘config.ini’</span>
</em>
So each element can be targeted separately in CSS, except that the parameter name and types are the same class. I would propose these should be separate. As mentioned in the OP, a good use case is where the type has a space in it (like above), and a design may want to add the style white-space:nowrap; to it so that you can't line-break in the middle of a type. Of course there are other reasons for styling them differently, since they are semantically different.
The output with autodoc_typehints = "description" does not have a different class name for each piece. Of course the HTML generated here is totally different altogether (e.g. generating links for the types), but thought it was worth collecting that info in the ticket.
Now we give a type of lexical token as a class of each element (Strictly, type annotation is not a "token", I know). n means a name, o means an operator and p means a puncture. It's an idea of pygments. I think both argument name and type annotation are also okay to add "nowrap" style.
BTW, about "description" mode, it is another matter. So please file a new issue to do that. I'll work for it during 3.x (if possible).
I think this issue was improved much. So I'm closing this now. If you still have a proposal, please file a new proposal.
Thanks,
Most helpful comment
This looks fantastic! As a preview to any readers, suppose we have a function with the following signature:
With the
conf.pyparameterautodoc_typehints = "signature", Sphinx previously would generate the following HTML for the parameter:now, it generates:
So each element can be targeted separately in CSS, except that the parameter name and types are the same class. I would propose these should be separate. As mentioned in the OP, a good use case is where the type has a space in it (like above), and a design may want to add the style
white-space:nowrap;to it so that you can't line-break in the middle of a type. Of course there are other reasons for styling them differently, since they are semantically different.The output with
autodoc_typehints = "description"does not have a different class name for each piece. Of course the HTML generated here is totally different altogether (e.g. generating links for the types), but thought it was worth collecting that info in the ticket.