From 257d392217974a76231e306133288748c7b70786 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sun, 9 Jul 2023 15:52:41 -0700 Subject: [PATCH] Fix removed comments in stub files (#3745) --- CHANGES.md | 2 ++ src/black/nodes.py | 11 ++++++- tests/data/simple_cases/ignore_pyi.py | 41 +++++++++++++++++++++++++++ tests/test_format.py | 5 ++-- 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 tests/data/simple_cases/ignore_pyi.py diff --git a/CHANGES.md b/CHANGES.md index 93d8ee1..bb30429 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,8 @@ - Fix a bug where an illegal trailing comma was added to return type annotations using PEP 604 unions (#3735) +- Fix several bugs and crashes where comments in stub files were removed or mishandled + under some circumstances. (#3745) - Fix a bug where multi-line open parenthesis magic comment like `type: ignore` were not correctly parsed (#3740) diff --git a/src/black/nodes.py b/src/black/nodes.py index ef42278..45423b2 100644 --- a/src/black/nodes.py +++ b/src/black/nodes.py @@ -714,6 +714,11 @@ def is_multiline_string(leaf: Leaf) -> bool: def is_stub_suite(node: Node) -> bool: """Return True if `node` is a suite with a stub body.""" + + # If there is a comment, we want to keep it. + if node.prefix.strip(): + return False + if ( len(node.children) != 4 or node.children[0].type != token.NEWLINE @@ -722,6 +727,9 @@ def is_stub_suite(node: Node) -> bool: ): return False + if node.children[3].prefix.strip(): + return False + return is_stub_body(node.children[2]) @@ -735,7 +743,8 @@ def is_stub_body(node: LN) -> bool: child = node.children[0] return ( - child.type == syms.atom + not child.prefix.strip() + and child.type == syms.atom and len(child.children) == 3 and all(leaf == Leaf(token.DOT, ".") for leaf in child.children) ) diff --git a/tests/data/simple_cases/ignore_pyi.py b/tests/data/simple_cases/ignore_pyi.py new file mode 100644 index 0000000..3ef6107 --- /dev/null +++ b/tests/data/simple_cases/ignore_pyi.py @@ -0,0 +1,41 @@ +def f(): # type: ignore + ... + +class x: # some comment + ... + +class y: + ... # comment + +# whitespace doesn't matter (note the next line has a trailing space and tab) +class z: + ... + +def g(): + # hi + ... + +def h(): + ... + # bye + +# output + +def f(): # type: ignore + ... + +class x: # some comment + ... + +class y: ... # comment + +# whitespace doesn't matter (note the next line has a trailing space and tab) +class z: ... + +def g(): + # hi + ... + +def h(): + ... + # bye diff --git a/tests/test_format.py b/tests/test_format.py index 8e0ada9..fb4d8eb 100644 --- a/tests/test_format.py +++ b/tests/test_format.py @@ -33,9 +33,10 @@ def check_file( @pytest.mark.parametrize("filename", all_data_cases("simple_cases")) def test_simple_format(filename: str) -> None: magic_trailing_comma = filename != "skip_magic_trailing_comma" - check_file( - "simple_cases", filename, black.Mode(magic_trailing_comma=magic_trailing_comma) + mode = black.Mode( + magic_trailing_comma=magic_trailing_comma, is_pyi=filename.endswith("_pyi") ) + check_file("simple_cases", filename, mode) @pytest.mark.parametrize("filename", all_data_cases("preview")) -- 2.39.5