Class new line between docstrings / vars / methods (#219)
Partially addresses #144
This commit is contained in:
parent
2ff05f2584
commit
e818260f1a
28
black.py
28
black.py
@ -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
|
||||||
|
@ -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
|
||||||
|
42
tests/class_methods_new_line.py
Normal file
42
tests/class_methods_new_line.py
Normal 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
|
@ -1,5 +1,4 @@
|
|||||||
class C:
|
class C:
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("post_data", "message"),
|
("post_data", "message"),
|
||||||
[
|
[
|
||||||
|
@ -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(
|
||||||
|
@ -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 = []
|
||||||
|
Loading…
Reference in New Issue
Block a user