From 9aea9768cb60d23f2f4d331e94c4ee07ef1683a5 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Mon, 11 Dec 2023 13:19:02 -0800 Subject: [PATCH] Only use dummy implementation logic for functions and classes (#4066) Fixes #4063 --- CHANGES.md | 2 ++ src/black/linegen.py | 4 ++-- src/black/nodes.py | 9 +++++++- .../cases/preview_dummy_implementations.py | 22 +++++++++++++++++-- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index fa0d2494f67..62caea41c31 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,8 @@ - Allow empty lines at the beginning of all blocks, except immediately before a docstring (#4060) - Fix crash in preview mode when using a short `--line-length` (#4086) +- Keep suites consisting of only an ellipsis on their own lines if they are not + functions or class definitions (#4066) ### Configuration diff --git a/src/black/linegen.py b/src/black/linegen.py index 073672a5ae7..6934823d340 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -286,7 +286,7 @@ def visit_suite(self, node: Node) -> Iterator[Line]: """Visit a suite.""" if ( self.mode.is_pyi or Preview.dummy_implementations in self.mode - ) and is_stub_suite(node): + ) and is_stub_suite(node, self.mode): yield from self.visit(node.children[2]) else: yield from self.visit_default(node) @@ -314,7 +314,7 @@ def visit_simple_stmt(self, node: Node) -> Iterator[Line]: if ( not (self.mode.is_pyi or Preview.dummy_implementations in self.mode) or not node.parent - or not is_stub_suite(node.parent) + or not is_stub_suite(node.parent, self.mode) ): yield from self.line() yield from self.visit_default(node) diff --git a/src/black/nodes.py b/src/black/nodes.py index de53f8e36a3..9b8d9a97835 100644 --- a/src/black/nodes.py +++ b/src/black/nodes.py @@ -736,8 +736,15 @@ def is_funcdef(node: Node) -> bool: return node.type == syms.funcdef -def is_stub_suite(node: Node) -> bool: +def is_stub_suite(node: Node, mode: Mode) -> bool: """Return True if `node` is a suite with a stub body.""" + if node.parent is not None: + if Preview.dummy_implementations in mode and node.parent.type not in ( + syms.funcdef, + syms.async_funcdef, + syms.classdef, + ): + return False # If there is a comment, we want to keep it. if node.prefix.strip(): diff --git a/tests/data/cases/preview_dummy_implementations.py b/tests/data/cases/preview_dummy_implementations.py index 98b69bf87b2..113ac36cdc5 100644 --- a/tests/data/cases/preview_dummy_implementations.py +++ b/tests/data/cases/preview_dummy_implementations.py @@ -1,9 +1,11 @@ # flags: --preview from typing import NoReturn, Protocol, Union, overload +class Empty: + ... def dummy(a): ... -def other(b): ... +async def other(b): ... @overload @@ -48,13 +50,22 @@ def b(arg: Union[int, str, object]) -> Union[int, str]: raise TypeError return arg +def has_comment(): + ... # still a dummy + +if some_condition: + ... + # output from typing import NoReturn, Protocol, Union, overload +class Empty: ... + + def dummy(a): ... -def other(b): ... +async def other(b): ... @overload @@ -98,3 +109,10 @@ def b(arg: Union[int, str, object]) -> Union[int, str]: if not isinstance(arg, (int, str)): raise TypeError return arg + + +def has_comment(): ... # still a dummy + + +if some_condition: + ...