-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Format empty lines in stub files like black's preview style #7206
Merged
Merged
Changes from 1 commit
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
crates/ruff_python_formatter/resources/test/fixtures/ruff/module_dangling_comment1.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
__all__ = ["X", "XK", "Xatom", "Xcursorfont", "Xutil", "display", "error", "rdb"] | ||
|
||
# Shared types throughout the stub |
2 changes: 2 additions & 0 deletions
2
crates/ruff_python_formatter/resources/test/fixtures/ruff/module_dangling_comment2.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
__all__ = ["X", "XK", "Xatom", "Xcursorfont", "Xutil", "display", "error", "rdb"] | ||
# Shared types throughout the stub |
7 changes: 7 additions & 0 deletions
7
crates/ruff_python_formatter/resources/test/fixtures/ruff/stub_files/comments.pyi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
class SupportsAnext: | ||
def __anext__(self): ... | ||
|
||
# Comparison protocols | ||
|
||
class SupportsDunderLT: | ||
def __init__(self): ... |
31 changes: 31 additions & 0 deletions
31
crates/ruff_python_formatter/resources/test/fixtures/ruff/stub_files/nesting.pyi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
"""Tests specifically for https://github.com/psf/black/issues/3861""" | ||
|
||
import sys | ||
|
||
|
||
class OuterClassOrOtherSuite: | ||
class Nested11: | ||
class Nested12: | ||
assignment = 1 | ||
def function_definition(self): ... | ||
|
||
def f1(self) -> str: ... | ||
|
||
class Nested21: | ||
class Nested22: | ||
def function_definition(self): ... | ||
assignment = 1 | ||
|
||
def f2(self) -> str: ... | ||
|
||
if sys.version_info > (3, 7): | ||
if sys.platform == "win32": | ||
assignment = 1 | ||
def function_definition(self): ... | ||
|
||
def f1(self) -> str: ... | ||
if sys.platform != "win32": | ||
def function_definition(self): ... | ||
assignment = 1 | ||
|
||
def f2(self) -> str: ... |
149 changes: 149 additions & 0 deletions
149
crates/ruff_python_formatter/resources/test/fixtures/ruff/stub_files/suite.pyi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
"""Tests for empty line rules in stub files, mostly inspired by typeshed. | ||
The rules are a list of nested exceptions. See also | ||
https://github.com/psf/black/blob/c160e4b7ce30c661ac4f2dfa5038becf1b8c5c33/src/black/lines.py#L576-L744 | ||
""" | ||
|
||
import sys | ||
from typing import Self, TypeAlias, final | ||
|
||
if sys.version_info >= (3, 8): | ||
class InnerClass1: ... | ||
|
||
class InnerClass2: | ||
def a(self): ... | ||
|
||
class InnerClass3: | ||
def a(self): ... | ||
|
||
class InnerClass4: ... | ||
details: int | ||
def f1(self, hresult: int, text: str | None, detail: int) -> None: ... | ||
details: int | ||
def f2(self, hresult: int, text: str | None, detail: int) -> None: ... | ||
@final | ||
class DecoratorInsteadOfEmptyLine: ... | ||
|
||
def open(device: str) -> None: ... | ||
|
||
# oss_mixer_device return type | ||
def openmixer(device: str = ...) -> None: ... | ||
def open2(device: str) -> None: ... | ||
# oss_mixer_device2 return type | ||
def openmixer2(device: str = ...) -> None: ... | ||
|
||
else: | ||
class Slice1: ... | ||
_Slice1: TypeAlias = Slice1 | ||
|
||
class Slice2: ... | ||
_Slice2: TypeAlias = Slice2 | ||
|
||
class NoEmptyLinesBetweenFunctions: | ||
def multi_line_but_only_ellipsis( | ||
self, | ||
mandatory_release: float | None, | ||
) -> None: ... | ||
def only_ellipsis1(self) -> float: ... | ||
def only_ellipsis2(self) -> float | None: ... | ||
def has_impl1(self): | ||
print(self) | ||
return 1 | ||
|
||
def has_impl2(self): | ||
print(self) | ||
return 2 | ||
|
||
def no_impl4(self): ... | ||
|
||
class NoEmptyLinesBetweenField: | ||
field1: int | ||
field2: ( | ||
# type | ||
int | ||
) | ||
field3 = 3 | ||
field4 = ( | ||
1, | ||
2, | ||
) | ||
field5 = 5 | ||
|
||
class FieldAndFunctionsWithOptionalEmptyLines: | ||
details1: int | ||
def f1(self, hresult: int, text: str | None, detail: int) -> None: ... | ||
details2: int | ||
def f2(self, hresult: int, text: str | None, detail: int) -> None: ... | ||
details3: int | ||
|
||
class NewlinesBetweenStubInnerClasses: | ||
def f1(self): ... | ||
|
||
class InnerClass1: ... | ||
class InnerClass2: ... | ||
|
||
def f2(self): ... | ||
|
||
class InnerClass3: ... | ||
class InnerClass4: ... | ||
field = 1 | ||
|
||
class InnerClass3: ... | ||
class InnerClass4: ... | ||
|
||
def f3(self): ... | ||
@final | ||
class DecoratorInsteadOfEmptyLine: ... | ||
|
||
@final | ||
class DecoratorStillEmptyLine: ... | ||
|
||
class NewlinesBetweenInnerClasses: | ||
class InnerClass1: ... | ||
|
||
class InnerClass2: | ||
def a(self): ... | ||
|
||
class InnerClass3: | ||
def a(self): ... | ||
|
||
class InnerClass4: ... | ||
|
||
class InnerClass5: | ||
def a(self): ... | ||
field1 = 1 | ||
|
||
class InnerClass6: | ||
def a(self): ... | ||
|
||
def f1(self): ... | ||
|
||
class InnerClass7: | ||
def a(self): ... | ||
print("hi") | ||
|
||
class InnerClass8: | ||
def a(self): ... | ||
|
||
class ComplexStatements: | ||
# didn't match the name in the C implementation, | ||
# meaning it is only *safe* to pass it as a keyword argument on 3.12+ | ||
if sys.version_info >= (3, 12): | ||
@classmethod | ||
def fromtimestamp(cls, timestamp: float, tz: float | None = ...) -> Self: ... | ||
else: | ||
@classmethod | ||
def fromtimestamp(cls, __timestamp: float, tz: float | None = ...) -> Self: ... | ||
|
||
@classmethod | ||
def utcfromtimestamp(cls, __t: float) -> Self: ... | ||
if sys.version_info >= (3, 8): | ||
@classmethod | ||
def now(cls, tz: float | None = None) -> Self: ... | ||
else: | ||
@classmethod | ||
def now(cls, tz: None = None) -> Self: ... | ||
@classmethod | ||
def now2(cls, tz: float) -> Self: ... | ||
|
||
@classmethod | ||
def utcnow(cls) -> Self: ... |
17 changes: 17 additions & 0 deletions
17
crates/ruff_python_formatter/resources/test/fixtures/ruff/stub_files/top_level.pyi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from typing import final | ||
|
||
|
||
def count1(): ... | ||
def count2(): ... | ||
@final | ||
def count3(): ... | ||
@final | ||
class LockType1: ... | ||
|
||
def count4(): ... | ||
|
||
class LockType2: ... | ||
class LockType3: ... | ||
|
||
@final | ||
class LockType4: ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,36 @@ | ||
use ruff_formatter::prelude::hard_line_break; | ||
use ruff_formatter::write; | ||
use ruff_formatter::{Buffer, FormatResult}; | ||
use ruff_python_ast::ModModule; | ||
|
||
use crate::prelude::*; | ||
use crate::comments::{trailing_comments, SourceComment}; | ||
use crate::statement::suite::SuiteKind; | ||
use crate::{write, AsFormat, FormatNodeRule, PyFormatter}; | ||
|
||
#[derive(Default)] | ||
pub struct FormatModModule; | ||
|
||
impl FormatNodeRule<ModModule> for FormatModModule { | ||
fn fmt_fields(&self, item: &ModModule, f: &mut PyFormatter) -> FormatResult<()> { | ||
let ModModule { range: _, body } = item; | ||
let comments = f.context().comments().clone(); | ||
|
||
write!( | ||
f, | ||
[ | ||
body.format().with_options(SuiteKind::TopLevel), | ||
trailing_comments(comments.dangling(item)), | ||
// Trailing newline at the end of the file | ||
hard_line_break() | ||
] | ||
) | ||
} | ||
|
||
fn fmt_dangling_comments( | ||
&self, | ||
_dangling_comments: &[SourceComment], | ||
_f: &mut PyFormatter, | ||
) -> FormatResult<()> { | ||
// Handled as part of `fmt_fields` | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's a bit counterintuitive that the exceptions are the named cases
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should
empty_lines
be inlined intoempty_lines_before_trailing_comments
. It seems the function is only used instmt_function_def
andstmt_class_def
and both use the same implementation.