From 268dcb677ce80331e0ef104d8335c2ada32872fb Mon Sep 17 00:00:00 2001 From: "Yilei \"Dolee\" Yang" Date: Fri, 17 Mar 2023 21:39:21 -0700 Subject: [PATCH] Do not add an extra blank line to an import line that has fmt disabled (#3610) --- CHANGES.md | 3 +++ src/black/comments.py | 1 + src/black/lines.py | 21 +++++++++++++++++++++ src/blib2to3/pytree.py | 6 ++++++ tests/data/simple_cases/fmtonoff.py | 1 - tests/data/simple_cases/fmtpass_imports.py | 19 +++++++++++++++++++ 6 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 tests/data/simple_cases/fmtpass_imports.py diff --git a/CHANGES.md b/CHANGES.md index eff2640..06a0ab7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,9 @@ +- Import lines with `# fmt: skip` and `# fmt: off` no longer have an extra blank line + added when they are right after another import line (#3610) + ### Preview style diff --git a/src/black/comments.py b/src/black/comments.py index 7cf15bf..619123a 100644 --- a/src/black/comments.py +++ b/src/black/comments.py @@ -203,6 +203,7 @@ def convert_one_fmt_off_pair(node: Node) -> bool: STANDALONE_COMMENT, hidden_value, prefix=standalone_comment_prefix, + fmt_pass_converted_first_leaf=first_leaf_of(first), ), ) return True diff --git a/src/black/lines.py b/src/black/lines.py index 329dfc4..66bba14 100644 --- a/src/black/lines.py +++ b/src/black/lines.py @@ -195,6 +195,26 @@ class Line: return False return self.leaves[-1].type == token.COLON + def is_fmt_pass_converted( + self, *, first_leaf_matches: Optional[Callable[[Leaf], bool]] = None + ) -> bool: + """Is this line converted from fmt off/skip code? + + If first_leaf_matches is not None, it only returns True if the first + leaf of converted code matches. + """ + if len(self.leaves) != 1: + return False + leaf = self.leaves[0] + if ( + leaf.type != STANDALONE_COMMENT + or leaf.fmt_pass_converted_first_leaf is None + ): + return False + return first_leaf_matches is None or first_leaf_matches( + leaf.fmt_pass_converted_first_leaf + ) + def contains_standalone_comments(self, depth_limit: int = sys.maxsize) -> bool: """If so, needs to be split before emitting.""" for leaf in self.leaves: @@ -597,6 +617,7 @@ class EmptyLineTracker: self.previous_line and self.previous_line.is_import and not current_line.is_import + and not current_line.is_fmt_pass_converted(first_leaf_matches=is_import) and depth == self.previous_line.depth ): return (before or 1), 0 diff --git a/src/blib2to3/pytree.py b/src/blib2to3/pytree.py index 15a1420..ea60c89 100644 --- a/src/blib2to3/pytree.py +++ b/src/blib2to3/pytree.py @@ -392,6 +392,10 @@ class Leaf(Base): _prefix = "" # Whitespace and comments preceding this token in the input lineno: int = 0 # Line where this token starts in the input column: int = 0 # Column where this token starts in the input + # If not None, this Leaf is created by converting a block of fmt off/skip + # code, and `fmt_pass_converted_first_leaf` points to the first Leaf in the + # converted code. + fmt_pass_converted_first_leaf: Optional["Leaf"] = None def __init__( self, @@ -401,6 +405,7 @@ class Leaf(Base): prefix: Optional[Text] = None, fixers_applied: List[Any] = [], opening_bracket: Optional["Leaf"] = None, + fmt_pass_converted_first_leaf: Optional["Leaf"] = None, ) -> None: """ Initializer. @@ -419,6 +424,7 @@ class Leaf(Base): self.fixers_applied: Optional[List[Any]] = fixers_applied[:] self.children = [] self.opening_bracket = opening_bracket + self.fmt_pass_converted_first_leaf = fmt_pass_converted_first_leaf def __repr__(self) -> str: """Return a canonical string representation.""" diff --git a/tests/data/simple_cases/fmtonoff.py b/tests/data/simple_cases/fmtonoff.py index e40ea2c..d1f15cd 100644 --- a/tests/data/simple_cases/fmtonoff.py +++ b/tests/data/simple_cases/fmtonoff.py @@ -195,7 +195,6 @@ import sys from third_party import X, Y, Z from library import some_connection, some_decorator - # fmt: off from third_party import (X, Y, Z) diff --git a/tests/data/simple_cases/fmtpass_imports.py b/tests/data/simple_cases/fmtpass_imports.py new file mode 100644 index 0000000..8b3c0bc --- /dev/null +++ b/tests/data/simple_cases/fmtpass_imports.py @@ -0,0 +1,19 @@ +# Regression test for https://github.com/psf/black/issues/3438 + +import ast +import collections # fmt: skip +import dataclasses +# fmt: off +import os +# fmt: on +import pathlib + +import re # fmt: skip +import secrets + +# fmt: off +import sys +# fmt: on + +import tempfile +import zoneinfo -- 2.39.2