Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b0c2bcc

Browse files
Treat functions/classes in blocks as if they're nested (psfGH-2472)
* Treat functions/classes in blocks as if they're nested One curveball is that we still want two preceding newlines before blocks that are probably logically disconnected. In other words: if condition: def foo(): return "hi" # <- aside: this is the goal of this commit else: def foo(): return "cya" # <- the two newlines spacing here should stay # since this probably isn't related with open("db.json", encoding="utf-8") as f: data = f.read() Unfortunately that means we have to special case specific clause types instead of just being able to just for a colon leaf. The hack used here is to check whether we're adding preceding newlines for a standalone or dependent clause. "Standalone" being a clause that doesn't need another clause to be valid (eg. if) and vice versa. Co-authored-by: Jelle Zijlstra <[email protected]>
1 parent 8485191 commit b0c2bcc

4 files changed

Lines changed: 87 additions & 3 deletions

File tree

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
- Add `flake8-simplify` and `flake8-comprehensions` plugins (#2653)
1818
- Fix determination of f-string expression spans (#2654)
1919
- Fix parser error location on invalid syntax in a `match` statement (#2649)
20+
- Functions and classes in blocks now have more consistent surrounding spacing (#2472)
2021

2122
## 21.11b1
2223

src/black/lines.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,11 +447,31 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
447447
before = 0
448448
depth = current_line.depth
449449
while self.previous_defs and self.previous_defs[-1] >= depth:
450-
self.previous_defs.pop()
451450
if self.is_pyi:
452451
before = 0 if depth else 1
453452
else:
454-
before = 1 if depth else 2
453+
if depth:
454+
before = 1
455+
elif (
456+
not depth
457+
and self.previous_defs[-1]
458+
and current_line.leaves[-1].type == token.COLON
459+
and (
460+
current_line.leaves[0].value
461+
not in ("with", "try", "for", "while", "if", "match")
462+
)
463+
):
464+
# We shouldn't add two newlines between an indented function and
465+
# a dependent non-indented clause. This is to avoid issues with
466+
# conditional function definitions that are technically top-level
467+
# and therefore get two trailing newlines, but look weird and
468+
# inconsistent when they're followed by elif, else, etc. This is
469+
# worse because these functions only get *one* preceding newline
470+
# already.
471+
before = 1
472+
else:
473+
before = 2
474+
self.previous_defs.pop()
455475
if current_line.is_decorator or current_line.is_def or current_line.is_class:
456476
return self._maybe_empty_lines_for_class_or_def(current_line, before)
457477

src/black_primer/primer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
},
117117
"pyanalyze": {
118118
"cli_arguments": ["--experimental-string-processing"],
119-
"expect_formatting_changes": false,
119+
"expect_formatting_changes": true,
120120
"git_clone_url": "https://github.com/quora/pyanalyze.git",
121121
"long_checkout": false,
122122
"py_versions": ["all"]

tests/data/function2.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,35 @@ def inner():
2323
pass
2424
print("Inner defs should breathe a little.")
2525

26+
27+
if os.name == "posix":
28+
import termios
29+
def i_should_be_followed_by_only_one_newline():
30+
pass
31+
elif os.name == "nt":
32+
try:
33+
import msvcrt
34+
def i_should_be_followed_by_only_one_newline():
35+
pass
36+
37+
except ImportError:
38+
39+
def i_should_be_followed_by_only_one_newline():
40+
pass
41+
42+
elif False:
43+
44+
class IHopeYouAreHavingALovelyDay:
45+
def __call__(self):
46+
print("i_should_be_followed_by_only_one_newline")
47+
else:
48+
49+
def foo():
50+
pass
51+
52+
with hmm_but_this_should_get_two_preceding_newlines():
53+
pass
54+
2655
# output
2756

2857
def f(
@@ -56,3 +85,37 @@ def inner():
5685
pass
5786

5887
print("Inner defs should breathe a little.")
88+
89+
90+
if os.name == "posix":
91+
import termios
92+
93+
def i_should_be_followed_by_only_one_newline():
94+
pass
95+
96+
elif os.name == "nt":
97+
try:
98+
import msvcrt
99+
100+
def i_should_be_followed_by_only_one_newline():
101+
pass
102+
103+
except ImportError:
104+
105+
def i_should_be_followed_by_only_one_newline():
106+
pass
107+
108+
elif False:
109+
110+
class IHopeYouAreHavingALovelyDay:
111+
def __call__(self):
112+
print("i_should_be_followed_by_only_one_newline")
113+
114+
else:
115+
116+
def foo():
117+
pass
118+
119+
120+
with hmm_but_this_should_get_two_preceding_newlines():
121+
pass

0 commit comments

Comments
 (0)