Class new line between docstrings / vars / methods (#219)

Partially addresses #144
This commit is contained in:
Luka Sterbic 2018-05-29 08:48:59 +02:00 committed by Łukasz Langa
parent 2ff05f2584
commit e818260f1a
6 changed files with 78 additions and 4 deletions

View File

@ -987,6 +987,18 @@ def is_class_paren_empty(self) -> bool:
and self.leaves[3].value == ")" and self.leaves[3].value == ")"
) )
@property
def is_triple_quoted_string(self) -> bool:
"""Is the line a triple quoted docstring?"""
return (
bool(self)
and self.leaves[0].type == token.STRING
and (
self.leaves[0].value.startswith('"""')
or self.leaves[0].value.startswith("'''")
)
)
def contains_standalone_comments(self, depth_limit: int = sys.maxsize) -> bool: def contains_standalone_comments(self, depth_limit: int = sys.maxsize) -> bool:
"""If so, needs to be split before emitting.""" """If so, needs to be split before emitting."""
for leaf in self.leaves: for leaf in self.leaves:
@ -1194,6 +1206,7 @@ class EmptyLineTracker:
the prefix of the first leaf consists of optional newlines. Those newlines the prefix of the first leaf consists of optional newlines. Those newlines
are consumed by `maybe_empty_lines()` and included in the computation. are consumed by `maybe_empty_lines()` and included in the computation.
""" """
is_pyi: bool = False is_pyi: bool = False
previous_line: Optional[Line] = None previous_line: Optional[Line] = None
previous_after: int = 0 previous_after: int = 0
@ -1244,6 +1257,12 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
if self.previous_line.is_decorator: if self.previous_line.is_decorator:
return 0, 0 return 0, 0
if (
self.previous_line.is_class
and self.previous_line.depth != current_line.depth
):
return 0, 0
if ( if (
self.previous_line.is_comment self.previous_line.is_comment
and self.previous_line.depth == current_line.depth and self.previous_line.depth == current_line.depth
@ -1275,6 +1294,13 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
): ):
return (before or 1), 0 return (before or 1), 0
if (
self.previous_line
and self.previous_line.is_class
and current_line.is_triple_quoted_string
):
return before, 1
return before, 0 return before, 0
@ -1285,6 +1311,7 @@ class LineGenerator(Visitor[Line]):
Note: destroys the tree it's visiting by mutating prefixes of its leaves Note: destroys the tree it's visiting by mutating prefixes of its leaves
in ways that will no longer stringify to valid Python code on the tree. in ways that will no longer stringify to valid Python code on the tree.
""" """
is_pyi: bool = False is_pyi: bool = False
current_line: Line = Factory(Line) current_line: Line = Factory(Line)
remove_u_prefix: bool = False remove_u_prefix: bool = False
@ -2768,6 +2795,7 @@ def gen_python_files_in_dir(path: Path) -> Iterator[Path]:
@dataclass @dataclass
class Report: class Report:
"""Provides a reformatting counter. Can be rendered with `str(report)`.""" """Provides a reformatting counter. Can be rendered with `str(report)`."""
check: bool = False check: bool = False
quiet: bool = False quiet: bool = False
change_count: int = 0 change_count: int = 0

View File

@ -39,7 +39,6 @@ def test_func(self):
class ClassWithEmptyFunc(object): class ClassWithEmptyFunc(object):
def func_with_blank_parentheses(): def func_with_blank_parentheses():
return 5 return 5
@ -55,7 +54,6 @@ class InsideFunc:
class NormalClass: class NormalClass:
def func_for_testing(self, first, second): def func_for_testing(self, first, second):
sum = first + second sum = first + second
return sum return sum

View File

@ -0,0 +1,42 @@
class ClassSimplest:
pass
class ClassWithInit:
def __init__(self):
pass
class ClassWithInitAndVars:
cls_var = 100
def __init__(self):
pass
class ClassWithInitAndVarsAndDocstring:
"""Test class"""
cls_var = 100
def __init__(self):
pass
# output
class ClassSimplest:
pass
class ClassWithInit:
def __init__(self):
pass
class ClassWithInitAndVars:
cls_var = 100
def __init__(self):
pass
class ClassWithInitAndVarsAndDocstring:
"""Test class"""
cls_var = 100
def __init__(self):
pass

View File

@ -1,5 +1,4 @@
class C: class C:
@pytest.mark.parametrize( @pytest.mark.parametrize(
("post_data", "message"), ("post_data", "message"),
[ [

View File

@ -1,5 +1,4 @@
class C: class C:
def test(self) -> None: def test(self) -> None:
with patch("black.out", print): with patch("black.out", print):
self.assertEqual( self.assertEqual(

View File

@ -363,6 +363,14 @@ def test_remove_empty_parentheses_after_class(self) -> None:
black.assert_equivalent(source, actual) black.assert_equivalent(source, actual)
black.assert_stable(source, actual, line_length=ll) black.assert_stable(source, actual, line_length=ll)
@patch("black.dump_to_file", dump_to_stderr)
def test_new_line_between_class_and_code(self) -> None:
source, expected = read_data("class_methods_new_line")
actual = fs(source)
self.assertFormatEqual(expected, actual)
black.assert_equivalent(source, actual)
black.assert_stable(source, actual, line_length=ll)
def test_report(self) -> None: def test_report(self) -> None:
report = black.Report() report = black.Report()
out_lines = [] out_lines = []