Support sticky standalone comments (comments preceding defs, classes, and decorators)

Fixes #56
Fixes #154
This commit is contained in:
Łukasz Langa 2018-04-24 11:50:31 -07:00
parent 29e97d1d4a
commit 52fda8b0e9
8 changed files with 62 additions and 29 deletions

View File

@ -230,11 +230,9 @@ are always reformatted to fit minimal space, this whitespace is lost.
It will also insert proper spacing before and after function definitions.
It's one line before and after inner functions and two lines before and
after module-level functions. *Black* will put those empty lines also
between the function definition and any standalone comments that
immediately precede the given function. If you want to comment on the
entire function, use a docstring or put a leading comment in the function
body.
after module-level functions. *Black* will not put empty lines between
function/class definitions and standalone comments that immediately precede
the given function/class.
### Trailing commas
@ -532,6 +530,9 @@ More details can be found in [CONTRIBUTING](CONTRIBUTING.md).
* fixed comment indentation when a standalone comment closes a block (#16, #32)
* fixed standalone comments receiving extra empty lines if immediately preceding
a class, def, or decorator (#56, #154)
* fixed `--diff` not showing entire path (#130)
* fixed parsing of complex expressions after star and double stars in

View File

@ -1040,12 +1040,14 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
# Don't insert empty lines before the first line in the file.
return 0, 0
if self.previous_line and self.previous_line.is_decorator:
# Don't insert empty lines between decorators.
if self.previous_line.is_decorator:
return 0, 0
if is_decorator and self.previous_line and self.previous_line.is_comment:
# Don't insert empty lines between decorator comments.
if (
self.previous_line.is_comment
and self.previous_line.depth == current_line.depth
and before == 0
):
return 0, 0
newlines = 2

View File

@ -161,8 +161,6 @@ def inline_comments_in_brackets_ruin_everything():
# add_compiler(compilers[(7.1, 64)])
# Comment before function.
def inline_comments_in_brackets_ruin_everything():
if typedargslist:
parameters.children = [

View File

@ -27,5 +27,45 @@
except OSError:
print("problems")
import sys
# leading function comment
def wat():
...
# trailing function comment
# SECTION COMMENT
# leading 1
@deco1
# leading 2
@deco2(with_args=True)
# leading 3
@deco3
def decorated1():
...
# leading 1
@deco1
# leading 2
@deco2(with_args=True)
# leading function comment
def decorated1():
...
# Note: crappy but inevitable. The current design of EmptyLineTracker doesn't
# allow this to work correctly. The user will have to split those lines by
# hand.
some_instruction
# This comment should be split from `some_instruction` by two lines but isn't.
def g():
...
if __name__ == "__main__":
main()

View File

@ -1,8 +0,0 @@
@property
# TODO: X
@property
# TODO: Y
# TODO: Z
@property
def foo():
pass

View File

@ -1,3 +1,7 @@
"""Docstring."""
# leading comment
def f():
NO = ''
SPACE = ' '
@ -44,9 +48,11 @@ def f():
syms.dictsetmaker,
}:
return NO
###############################################################################
# SECTION BECAUSE SECTIONS
###############################################################################
def g():
NO = ''
SPACE = ' '
@ -89,6 +95,10 @@ def g():
# output
"""Docstring."""
# leading comment
def f():
NO = ""
SPACE = " "

View File

@ -119,8 +119,6 @@ async def coroutine(arg, exec=False):
def function_signature_stress_test(number:int,no_annotation=None,text:str='default',* ,debug:bool=False,**kwargs) -> str:
return text[number:-1]
# fmt: on
def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r""):
offset = attr.ib(default=attr.Factory(lambda: _r.uniform(10000, 200000)))
assert task._cancel_stack[:len(old_stack)] == old_stack

View File

@ -626,14 +626,6 @@ def test_check_diff_use_together(self) -> None:
)
self.assertEqual(result.exit_code, 1)
@patch("black.dump_to_file", dump_to_stderr)
def test_comment_in_decorator(self) -> None:
source, expected = read_data("comments6")
actual = fs(source)
self.assertFormatEqual(expected, actual)
black.assert_equivalent(source, actual)
black.assert_stable(source, actual, line_length=ll)
if __name__ == "__main__":
unittest.main()