[formatter] Fix missing blank lines before decorated classes in .pyi files (#18888)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run

Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
K 2025-06-24 19:55:44 +05:30 committed by GitHub
parent 02ae8e1210
commit 47653ca88a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 87 additions and 5 deletions

View file

@ -0,0 +1,9 @@
# Issue #18865: Decorated classes below functions should be separated with blank lines
def hello(): ...
@lambda _, /: _
class A: ...
def world(): ...
@final
class B: ...

View file

@ -20,3 +20,10 @@ pub(crate) const fn is_no_chaperone_for_escaped_quote_in_triple_quoted_docstring
) -> bool {
context.is_preview()
}
/// Returns `true` if the [`blank_line_before_decorated_class_in_stub`](https://github.com/astral-sh/ruff/issues/18865) preview style is enabled.
pub(crate) const fn is_blank_line_before_decorated_class_in_stub_enabled(
context: &PyFormatContext,
) -> bool {
context.is_preview()
}

View file

@ -13,6 +13,7 @@ use crate::comments::{
use crate::context::{NodeLevel, TopLevelStatementPosition, WithIndentLevel, WithNodeLevel};
use crate::other::string_literal::StringLiteralKind;
use crate::prelude::*;
use crate::preview::is_blank_line_before_decorated_class_in_stub_enabled;
use crate::statement::stmt_expr::FormatStmtExpr;
use crate::verbatim::{
suppressed_node, write_suppressed_statements_starting_with_leading_comment,
@ -700,10 +701,15 @@ fn stub_suite_can_omit_empty_line(preceding: &Stmt, following: &Stmt, f: &PyForm
//
// class LockType2: ...
// ```
let class_decorator_instead_of_empty_line = preceding.is_function_def_stmt()
&& following
.as_class_def_stmt()
.is_some_and(|class| !class.decorator_list.is_empty());
//
// However, this behavior is incorrect and should not be replicated in preview mode.
// See: https://github.com/astral-sh/ruff/issues/18865
let class_decorator_instead_of_empty_line =
!is_blank_line_before_decorated_class_in_stub_enabled(f.context())
&& preceding.is_function_def_stmt()
&& following
.as_class_def_stmt()
.is_some_and(|class| !class.decorator_list.is_empty());
// A function definition following a stub function definition
// ```python

View file

@ -0,0 +1,46 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/stub_files/decorated_class_after_function.pyi
---
## Input
```python
# Issue #18865: Decorated classes below functions should be separated with blank lines
def hello(): ...
@lambda _, /: _
class A: ...
def world(): ...
@final
class B: ...
```
## Output
```python
# Issue #18865: Decorated classes below functions should be separated with blank lines
def hello(): ...
@lambda _, /: _
class A: ...
def world(): ...
@final
class B: ...
```
## Preview changes
```diff
--- Stable
+++ Preview
@@ -1,8 +1,10 @@
# Issue #18865: Decorated classes below functions should be separated with blank lines
def hello(): ...
+
@lambda _, /: _
class A: ...
def world(): ...
+
@final
class B: ...
```

View file

@ -1,7 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/stub_files/top_level.pyi
snapshot_kind: text
---
## Input
```python
@ -43,3 +42,18 @@ class LockType3: ...
@final
class LockType4: ...
```
## Preview changes
```diff
--- Stable
+++ Preview
@@ -4,6 +4,7 @@
def count2(): ...
@final
def count3(): ...
+
@final
class LockType1: ...
```