Skip to content
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

python: Improve formatting of signatures with type hints #5868

Closed
bdarnell opened this issue Dec 30, 2018 · 13 comments
Closed

python: Improve formatting of signatures with type hints #5868

bdarnell opened this issue Dec 30, 2018 · 13 comments
Labels
Milestone

Comments

@bdarnell
Copy link
Contributor

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:

image

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.

@tk0miya tk0miya added this to the some future version milestone Jan 2, 2019
@tk0miya
Copy link
Member

tk0miya commented Jan 2, 2019

+1; Reasonable.

@chernals
Copy link

chernals commented Jan 4, 2019

+1; This quickly becomes extremely ugly even for more minimal examples than the one above.

@timhoffm
Copy link
Contributor

timhoffm commented Jan 6, 2019

See also #4390.

@tk0miya
Copy link
Member

tk0miya commented May 29, 2019

Fixed by #4390.
Thanks,

@tk0miya tk0miya closed this as completed May 29, 2019
@tk0miya tk0miya reopened this May 29, 2019
@tk0miya
Copy link
Member

tk0miya commented May 29, 2019

Sorry for my wrong. Reopened.

@sotte
Copy link

sotte commented Nov 3, 2019

How could we proceed with this issue?

@chernals
Copy link

chernals commented Nov 3, 2019

@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.

@tk0miya tk0miya modified the milestones: some future version, 3.0.0 Nov 5, 2019
@alkasm
Copy link

alkasm commented Feb 9, 2020

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.

@tk0miya
Copy link
Member

tk0miya commented Feb 9, 2020

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.

@tk0miya
Copy link
Member

tk0miya commented Mar 14, 2020

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?

@tk0miya tk0miya modified the milestones: 3.0.0, 3.1.0 Mar 14, 2020
@alkasm
Copy link

alkasm commented Mar 17, 2020

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.

@tk0miya
Copy link
Member

tk0miya commented Mar 18, 2020

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).

@tk0miya
Copy link
Member

tk0miya commented May 23, 2020

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,

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

6 participants