Black: Breaks multiline function type annotation comments

Created on 31 May 2018  Â·  8Comments  Â·  Source: psf/black

Operating system: Fedora 27 4.13.9-300.fc27.x86_64)
Python version: 3.6.2
Black version: 18.5b1
Does also happen on master: yes

PEP484 was amended (https://github.com/python/typing/issues/186) to extend Python 2 compatible type annotation comments to allow placing each function parameter on a separate line with its own type annotation and the return type at the end. The motivation for this was to be able to write type annotations which would otherwise extend beyond the maximum line limit. But when it will fit in the maximum line length, Black combines all the arguments onto one line, including the type annotations, which become malformed.

Given this input

def f(a,  # type: int
      b,  # type: str
      c,  # type: bool
      ):  # type: (...) -> None
    ...

Black produces this

def f(a, b, c):  # type: int  # type: str  # type: bool  # type: (...) -> None
    ...

which has a malformed type annotation.

I think the correct behaviour would be either leave the function parameters on separate lines (do nothing) or restructure the type annotation like this:

def f(a, b, c):  # (int, str, bool) -> None
    ...

or if the resultant line is too long, this

def f(a, b, c): 
    # (int, str, bool) -> None
    ...

This might deserve a separate issue, but it'd be nice if Black did the reverse as well: given a very long function type annotation on one line, annotate each parameter separately.

bug comments design

Most helpful comment

Noting that this is a more general issue with inline comments. For example, black changes the meaning of this comment intended to be associated with a particular kwarg:

$ cat example.py
myfunc(
    a,
    b=1,  # this is critical due to #123
    c=None)

$ black example.py
reformatted example.py

$ cat example.py
myfunc(a, b=1, c=None)  # this is critical due to #123

All 8 comments

Yes, this is unfortunate and I should probably have special handling for it. Not quite clear how I would special-case it yet.

Noting that this is a more general issue with inline comments. For example, black changes the meaning of this comment intended to be associated with a particular kwarg:

$ cat example.py
myfunc(
    a,
    b=1,  # this is critical due to #123
    c=None)

$ black example.py
reformatted example.py

$ cat example.py
myfunc(a, b=1, c=None)  # this is critical due to #123

@perrygeo, that's intentional.

There are many cases where neither of the suggestions (apart from 'do nothing') from @ned will work without making a line that is too long. Usually when I use a multiline type annotation it's because it won't fit on a single line after the function. That is,

def f(a, b, c): 
    # (int, str, bool) -> None

in some cases would cause the type annotation # (int, str, bool) -> None to extend beyond the character limit. In these cases, Black should probably do nothing at all.

I just ran into this as well. We're still on Python 2 (just a little bit longer now…) and I'd like to adopt Black, but this is a showstopper.

Thinking about it more, I wonder if maybe Black shouldn't be moving comments inside lists at all. Aside from that pattern being used for human-readable comments (perrygeo's example above), it is also universal among tools that work with Python code:

mypy:

def func(
    arg1,  # type: int
    arg2,  # type: int
):

flake8:

foo(
    f(),
    g(),  # noqa: E123
):

pylint:

obj.things = [
    a.b,
    c.d,  # pylint: disable=no-member
]

isort:

from os import (
    path,  # isort:skip
    setenv,
    getenv,
)

coverage.py:

foo(
    x() if cover_me else y(),
    a() if ignore_me else b(),  # pragma: no cover
)

In each of these cases, moving the comment away from its line would either weaken the intended semantics or break things entirely. So maybe this issue is a little further-reaching than just Python 2 + mypy.

A small plug for #642 -- until this issue is fixed we won't be able to use black at Dropbox. We use this syntax extensively.

Fixed by #642.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

brettcannon picture brettcannon  Â·  3Comments

craigmac picture craigmac  Â·  3Comments

dimaqq picture dimaqq  Â·  3Comments

bhearsum picture bhearsum  Â·  3Comments

uranusjr picture uranusjr  Â·  3Comments