Format class definitions (#5289)

This commit is contained in:
Micha Reiser 2023-06-22 11:09:43 +02:00 committed by GitHub
parent 7d4f8e59da
commit f7e1cf4b51
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 914 additions and 541 deletions

View file

@ -582,6 +582,12 @@ fn handle_trailing_end_of_line_condition_comment<'a>(
.as_deref()
.map(AnyNodeRef::from)
.or_else(|| Some(AnyNodeRef::from(args.as_ref()))),
AnyNodeRef::StmtClassDef(StmtClassDef {
bases, keywords, ..
}) => keywords
.last()
.map(AnyNodeRef::from)
.or_else(|| bases.last().map(AnyNodeRef::from)),
_ => None,
};
@ -622,8 +628,13 @@ fn handle_trailing_end_of_line_condition_comment<'a>(
TokenKind::RParen => {
// Skip over any closing parentheses
}
_ => {
unreachable!("Only ')' or ':' should follow the condition")
TokenKind::Comma => {
// Skip over any trailing comma
}
kind => {
unreachable!(
"Only ')' or ':' should follow the condition but encountered {kind:?}"
)
}
}
}

View file

@ -26,6 +26,8 @@ pub(super) fn default_expression_needs_parentheses(
#[allow(clippy::if_same_then_else)]
if parenthesize.is_always() {
Parentheses::Always
} else if parenthesize.is_never() {
Parentheses::Never
}
// `Optional` or `Preserve` and expression has parentheses in source code.
else if !parenthesize.is_if_breaks() && is_expression_parenthesized(node, source) {
@ -58,7 +60,11 @@ pub enum Parenthesize {
/// Parenthesizes the expression only if it doesn't fit on a line.
IfBreaks,
/// Always adds parentheses
Always,
/// Never adds parentheses. Parentheses are handled by the caller.
Never,
}
impl Parenthesize {
@ -66,6 +72,10 @@ impl Parenthesize {
matches!(self, Parenthesize::Always)
}
pub(crate) const fn is_never(self) -> bool {
matches!(self, Parenthesize::Never)
}
pub(crate) const fn is_if_breaks(self) -> bool {
matches!(self, Parenthesize::IfBreaks)
}

View file

@ -1,5 +1,6 @@
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult};
use crate::prelude::*;
use crate::FormatNodeRule;
use ruff_formatter::write;
use rustpython_parser::ast::Keyword;
#[derive(Default)]
@ -7,6 +8,15 @@ pub struct FormatKeyword;
impl FormatNodeRule<Keyword> for FormatKeyword {
fn fmt_fields(&self, item: &Keyword, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [not_yet_implemented(item)])
let Keyword {
range: _,
arg,
value,
} = item;
if let Some(argument) = arg {
write!(f, [argument.format(), text("=")])?;
}
value.format().fmt(f)
}
}

View file

@ -1,135 +0,0 @@
---
source: crates/ruff_python_formatter/src/lib.rs
expression: snapshot
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/class_blank_parentheses.py
---
## Input
```py
class SimpleClassWithBlankParentheses():
pass
class ClassWithSpaceParentheses ( ):
first_test_data = 90
second_test_data = 100
def test_func(self):
return None
class ClassWithEmptyFunc(object):
def func_with_blank_parentheses():
return 5
def public_func_with_blank_parentheses():
return None
def class_under_the_func_with_blank_parentheses():
class InsideFunc():
pass
class NormalClass (
):
def func_for_testing(self, first, second):
sum = first + second
return sum
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,18 +1,10 @@
-class SimpleClassWithBlankParentheses:
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
-class ClassWithSpaceParentheses:
- first_test_data = 90
- second_test_data = 100
-
- def test_func(self):
- return None
+NOT_YET_IMPLEMENTED_StmtClassDef
-class ClassWithEmptyFunc(object):
- def func_with_blank_parentheses():
- return 5
+NOT_YET_IMPLEMENTED_StmtClassDef
def public_func_with_blank_parentheses():
@@ -20,11 +12,7 @@
def class_under_the_func_with_blank_parentheses():
- class InsideFunc:
- pass
+ NOT_YET_IMPLEMENTED_StmtClassDef
-class NormalClass:
- def func_for_testing(self, first, second):
- sum = first + second
- return sum
+NOT_YET_IMPLEMENTED_StmtClassDef
```
## Ruff Output
```py
NOT_YET_IMPLEMENTED_StmtClassDef
NOT_YET_IMPLEMENTED_StmtClassDef
NOT_YET_IMPLEMENTED_StmtClassDef
def public_func_with_blank_parentheses():
return None
def class_under_the_func_with_blank_parentheses():
NOT_YET_IMPLEMENTED_StmtClassDef
NOT_YET_IMPLEMENTED_StmtClassDef
```
## Black Output
```py
class SimpleClassWithBlankParentheses:
pass
class ClassWithSpaceParentheses:
first_test_data = 90
second_test_data = 100
def test_func(self):
return None
class ClassWithEmptyFunc(object):
def func_with_blank_parentheses():
return 5
def public_func_with_blank_parentheses():
return None
def class_under_the_func_with_blank_parentheses():
class InsideFunc:
pass
class NormalClass:
def func_for_testing(self, first, second):
sum = first + second
return sum
```

View file

@ -113,259 +113,257 @@ class ClassWithDecoInitAndVarsAndDocstringWithInner2:
```diff
--- Black
+++ Ruff
@@ -1,165 +1,61 @@
-class ClassSimplest:
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
@@ -7,7 +7,7 @@
-class ClassWithSingleField:
- a = 1
+NOT_YET_IMPLEMENTED_StmtClassDef
-class ClassWithJustTheDocstring:
class ClassWithJustTheDocstring:
- """Just a docstring."""
+NOT_YET_IMPLEMENTED_StmtClassDef
+ "NOT_YET_IMPLEMENTED_STRING"
-class ClassWithInit:
- def __init__(self):
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithInit:
@@ -16,7 +16,7 @@
-class ClassWithTheDocstringAndInit:
class ClassWithTheDocstringAndInit:
- """Just a docstring."""
+NOT_YET_IMPLEMENTED_StmtClassDef
+ "NOT_YET_IMPLEMENTED_STRING"
- def __init__(self):
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
-class ClassWithInitAndVars:
- cls_var = 100
- def __init__(self):
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
def __init__(self):
pass
@@ -30,8 +30,7 @@
-class ClassWithInitAndVarsAndDocstring:
class ClassWithInitAndVarsAndDocstring:
- """Test class"""
+NOT_YET_IMPLEMENTED_StmtClassDef
-
+ "NOT_YET_IMPLEMENTED_STRING"
cls_var = 100
- cls_var = 100
- def __init__(self):
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
def __init__(self):
@@ -53,8 +52,7 @@
-class ClassWithDecoInit:
- @deco
- def __init__(self):
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
-class ClassWithDecoInitAndVars:
- cls_var = 100
+NOT_YET_IMPLEMENTED_StmtClassDef
- @deco
- def __init__(self):
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
-class ClassWithDecoInitAndVarsAndDocstring:
class ClassWithDecoInitAndVarsAndDocstring:
- """Test class"""
-
+ "NOT_YET_IMPLEMENTED_STRING"
cls_var = 100
- cls_var = 100
+NOT_YET_IMPLEMENTED_StmtClassDef
@deco
@@ -69,7 +67,7 @@
- @deco
- def __init__(self):
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
-class ClassSimplestWithInner:
- class Inner:
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
-class ClassSimplestWithInnerWithDocstring:
- class Inner:
class ClassSimplestWithInnerWithDocstring:
class Inner:
- """Just a docstring."""
+ "NOT_YET_IMPLEMENTED_STRING"
- def __init__(self):
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
def __init__(self):
pass
@@ -83,7 +81,7 @@
-class ClassWithSingleFieldWithInner:
- a = 1
+NOT_YET_IMPLEMENTED_StmtClassDef
- class Inner:
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
-class ClassWithJustTheDocstringWithInner:
class ClassWithJustTheDocstringWithInner:
- """Just a docstring."""
+ "NOT_YET_IMPLEMENTED_STRING"
- class Inner:
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
class Inner:
pass
@@ -108,8 +106,7 @@
-class ClassWithInitWithInner:
- class Inner:
- pass
-
- def __init__(self):
- pass
-
-
-class ClassWithInitAndVarsWithInner:
- cls_var = 100
-
- class Inner:
- pass
-
- def __init__(self):
- pass
-
-
-class ClassWithInitAndVarsAndDocstringWithInner:
class ClassWithInitAndVarsAndDocstringWithInner:
- """Test class"""
-
- cls_var = 100
-
- class Inner:
- pass
-
- def __init__(self):
- pass
-
-
-class ClassWithDecoInitWithInner:
- class Inner:
- pass
-
- @deco
- def __init__(self):
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
+ "NOT_YET_IMPLEMENTED_STRING"
cls_var = 100
class Inner:
@@ -140,8 +137,7 @@
-class ClassWithDecoInitAndVarsWithInner:
- cls_var = 100
-
- class Inner:
- pass
-
- @deco
- def __init__(self):
- pass
-
-
-class ClassWithDecoInitAndVarsAndDocstringWithInner:
class ClassWithDecoInitAndVarsAndDocstringWithInner:
- """Test class"""
-
- cls_var = 100
-
- class Inner:
- pass
-
- @deco
- def __init__(self):
- pass
-
-
-class ClassWithDecoInitAndVarsAndDocstringWithInner2:
+ "NOT_YET_IMPLEMENTED_STRING"
cls_var = 100
class Inner:
@@ -153,7 +149,7 @@
class ClassWithDecoInitAndVarsAndDocstringWithInner2:
- """Test class"""
-
- class Inner:
- pass
-
- cls_var = 100
-
- @deco
- def __init__(self):
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
+ "NOT_YET_IMPLEMENTED_STRING"
class Inner:
pass
```
## Ruff Output
```py
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassSimplest:
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithSingleField:
a = 1
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithJustTheDocstring:
"NOT_YET_IMPLEMENTED_STRING"
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithInit:
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithTheDocstringAndInit:
"NOT_YET_IMPLEMENTED_STRING"
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithInitAndVars:
cls_var = 100
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithInitAndVarsAndDocstring:
"NOT_YET_IMPLEMENTED_STRING"
cls_var = 100
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithDecoInit:
@deco
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithDecoInitAndVars:
cls_var = 100
@deco
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithDecoInitAndVarsAndDocstring:
"NOT_YET_IMPLEMENTED_STRING"
cls_var = 100
@deco
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassSimplestWithInner:
class Inner:
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassSimplestWithInnerWithDocstring:
class Inner:
"NOT_YET_IMPLEMENTED_STRING"
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithSingleFieldWithInner:
a = 1
class Inner:
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithJustTheDocstringWithInner:
"NOT_YET_IMPLEMENTED_STRING"
class Inner:
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithInitWithInner:
class Inner:
pass
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithInitAndVarsWithInner:
cls_var = 100
class Inner:
pass
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithInitAndVarsAndDocstringWithInner:
"NOT_YET_IMPLEMENTED_STRING"
cls_var = 100
class Inner:
pass
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithDecoInitWithInner:
class Inner:
pass
@deco
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithDecoInitAndVarsWithInner:
cls_var = 100
class Inner:
pass
@deco
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithDecoInitAndVarsAndDocstringWithInner:
"NOT_YET_IMPLEMENTED_STRING"
cls_var = 100
class Inner:
pass
@deco
def __init__(self):
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithDecoInitAndVarsAndDocstringWithInner2:
"NOT_YET_IMPLEMENTED_STRING"
class Inner:
pass
cls_var = 100
@deco
def __init__(self):
pass
```
## Black Output

View file

@ -349,7 +349,7 @@ instruction()#comment with bad spacing
while True:
if False:
continue
@@ -141,25 +111,13 @@
@@ -141,24 +111,18 @@
# and round and round we go
# let's return
@ -370,15 +370,17 @@ instruction()#comment with bad spacing
+CONFIG_FILES = [CONFIG_FILE] + SHARED_CONFIG_FILES + USER_CONFIG_FILES # type: Final
-class Test:
- def _init_host(self, parsed) -> None:
class Test:
def _init_host(self, parsed) -> None:
- if parsed.hostname is None or not parsed.hostname.strip(): # type: ignore
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
+ if (
+ NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right # type: ignore
+ or not NOT_IMPLEMENTED_call()
+ ):
pass
#######################
@@ -167,7 +125,7 @@
@@ -167,7 +131,7 @@
#######################
@ -511,7 +513,13 @@ def inline_comments_in_brackets_ruin_everything():
CONFIG_FILES = [CONFIG_FILE] + SHARED_CONFIG_FILES + USER_CONFIG_FILES # type: Final
NOT_YET_IMPLEMENTED_StmtClassDef
class Test:
def _init_host(self, parsed) -> None:
if (
NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right # type: ignore
or not NOT_IMPLEMENTED_call()
):
pass
#######################

View file

@ -107,7 +107,7 @@ def foo3(list_a, list_b):
```diff
--- Black
+++ Ruff
@@ -1,94 +1,22 @@
@@ -1,94 +1,28 @@
-from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
- MyLovelyCompanyTeamProjectComponent, # NOT DRY
-)
@ -118,7 +118,7 @@ def foo3(list_a, list_b):
+NOT_YET_IMPLEMENTED_StmtImportFrom
-class C:
class C:
- @pytest.mark.parametrize(
- ("post_data", "message"),
- [
@ -161,12 +161,14 @@ def foo3(list_a, list_b):
- ),
- ],
- )
- def test_fails_invalid_post_data(
- self, pyramid_config, db_request, post_data, message
- ):
+ @NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
def test_fails_invalid_post_data(
self, pyramid_config, db_request, post_data, message
):
- pyramid_config.testing_securitypolicy(userid=1)
- db_request.POST = MultiDict(post_data)
+NOT_YET_IMPLEMENTED_StmtClassDef
+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
+ db_request.POST = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
def foo(list_a, list_b):
@ -217,7 +219,13 @@ NOT_YET_IMPLEMENTED_StmtImportFrom
NOT_YET_IMPLEMENTED_StmtImportFrom
NOT_YET_IMPLEMENTED_StmtClassDef
class C:
@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
def test_fails_invalid_post_data(
self, pyramid_config, db_request, post_data, message
):
NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
db_request.POST = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
def foo(list_a, list_b):

View file

@ -152,38 +152,16 @@ def bar():
```diff
--- Black
+++ Ruff
@@ -30,8 +30,7 @@
@@ -44,7 +44,7 @@
# This comment should be split from the statement above by two lines.
-class MyClass:
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
some = statement
@@ -39,17 +38,14 @@
# This should be split from the above by two lines
-class MyClassWithComplexLeadingComments:
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
-class ClassWithDocstring:
class ClassWithDocstring:
- """A docstring."""
+NOT_YET_IMPLEMENTED_StmtClassDef
+ "NOT_YET_IMPLEMENTED_STRING"
# Leading comment after a class with just a docstring
-class MyClassAfterAnotherClassWithDocstring:
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
some = statement
@@ -59,7 +55,7 @@
@@ -59,7 +59,7 @@
@deco1
# leading 2
# leading 2 extra
@ -192,7 +170,7 @@ def bar():
# leading 3
@deco3
# leading 4
@@ -73,7 +69,7 @@
@@ -73,7 +73,7 @@
# leading 1
@deco1
# leading 2
@ -201,7 +179,7 @@ def bar():
# leading 3 that already has an empty line
@deco3
@@ -88,7 +84,7 @@
@@ -88,7 +88,7 @@
# leading 1
@deco1
# leading 2
@ -210,7 +188,7 @@ def bar():
# leading 3
@deco3
@@ -106,7 +102,6 @@
@@ -106,7 +106,6 @@
# Another leading comment
def another_inline():
pass
@ -218,7 +196,7 @@ def bar():
else:
# More leading comments
def inline_after_else():
@@ -121,18 +116,13 @@
@@ -121,7 +120,6 @@
# Another leading comment
def another_top_level_quote_inline_inline():
pass
@ -226,18 +204,6 @@ def bar():
else:
# More leading comments
def top_level_quote_inline_after_else():
pass
-class MyClass:
- # First method has no empty lines between bare class def.
- # More comments.
- def first_method(self):
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
# Regression test for https://github.com/psf/black/issues/3454.
```
## Ruff Output
@ -275,7 +241,8 @@ some = statement
# This comment should be split from the statement above by two lines.
NOT_YET_IMPLEMENTED_StmtClassDef
class MyClass:
pass
some = statement
@ -283,14 +250,17 @@ some = statement
# This should be split from the above by two lines
NOT_YET_IMPLEMENTED_StmtClassDef
class MyClassWithComplexLeadingComments:
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithDocstring:
"NOT_YET_IMPLEMENTED_STRING"
# Leading comment after a class with just a docstring
NOT_YET_IMPLEMENTED_StmtClassDef
class MyClassAfterAnotherClassWithDocstring:
pass
some = statement
@ -367,7 +337,11 @@ else:
pass
NOT_YET_IMPLEMENTED_StmtClassDef
class MyClass:
# First method has no empty lines between bare class def.
# More comments.
def first_method(self):
pass
# Regression test for https://github.com/psf/black/issues/3454.

View file

@ -114,16 +114,16 @@ async def wat():
# Has many lines. Many, many lines.
# Many, many, many lines.
-"""Module docstring.
-
+"NOT_YET_IMPLEMENTED_STRING"
-Possibly also many, many lines.
-"""
+"NOT_YET_IMPLEMENTED_STRING"
+NOT_YET_IMPLEMENTED_StmtImport
+NOT_YET_IMPLEMENTED_StmtImport
-import os.path
-import sys
+NOT_YET_IMPLEMENTED_StmtImport
+NOT_YET_IMPLEMENTED_StmtImport
-
-import a
-from b.c import X # some noqa comment
+NOT_YET_IMPLEMENTED_StmtImport
@ -137,7 +137,7 @@ async def wat():
# Some comment before a function.
@@ -30,67 +24,50 @@
@@ -30,25 +24,26 @@
def function(default=None):
@ -173,28 +173,29 @@ async def wat():
# Another comment!
# This time two lines.
@@ -56,7 +51,7 @@
-class Foo:
class Foo:
- """Docstring for class Foo. Example from Sphinx docs."""
-
- #: Doc comment for class attribute Foo.bar.
- #: It can have multiple lines.
- bar = 1
-
- flox = 1.5 #: Doc comment for Foo.flox. One line only.
-
- baz = 2
+ "NOT_YET_IMPLEMENTED_STRING"
#: Doc comment for class attribute Foo.bar.
#: It can have multiple lines.
@@ -65,32 +60,31 @@
flox = 1.5 #: Doc comment for Foo.flox. One line only.
baz = 2
- """Docstring for class attribute Foo.baz."""
-
- def __init__(self):
- #: Doc comment for instance attribute qux.
- self.qux = 3
-
- self.spam = 4
+ "NOT_YET_IMPLEMENTED_STRING"
def __init__(self):
#: Doc comment for instance attribute qux.
self.qux = 3
self.spam = 4
- """Docstring for instance attribute spam."""
+NOT_YET_IMPLEMENTED_StmtClassDef
+ "NOT_YET_IMPLEMENTED_STRING"
#' <h1>This is pweave!</h1>
@ -279,7 +280,24 @@ GLOBAL_STATE = {
# This time two lines.
NOT_YET_IMPLEMENTED_StmtClassDef
class Foo:
"NOT_YET_IMPLEMENTED_STRING"
#: Doc comment for class attribute Foo.bar.
#: It can have multiple lines.
bar = 1
flox = 1.5 #: Doc comment for Foo.flox. One line only.
baz = 2
"NOT_YET_IMPLEMENTED_STRING"
def __init__(self):
#: Doc comment for instance attribute qux.
self.qux = 3
self.spam = 4
"NOT_YET_IMPLEMENTED_STRING"
#' <h1>This is pweave!</h1>

View file

@ -194,9 +194,9 @@ class C:
```diff
--- Black
+++ Ruff
@@ -1,181 +1 @@
-class C:
- def test(self) -> None:
@@ -1,181 +1,46 @@
class C:
def test(self) -> None:
- with patch("black.out", print):
- self.assertEqual(
- unstyle(str(report)), "1 file reformatted, 1 file failed to reformat."
@ -239,23 +239,38 @@ class C:
- return (
- 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
- % (test.name, test.filename, lineno, lname, err)
- )
-
- def omitting_trailers(self) -> None:
+ NOT_YET_IMPLEMENTED_StmtWith
+ xxxxxxxxxxxxxxxx = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
+ return "NOT_YET_IMPLEMENTED_STRING" % (
+ test.name,
+ test.filename,
+ lineno,
+ lname,
+ err,
)
def omitting_trailers(self) -> None:
- get_collection(
- hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
- )[OneLevelIndex]
- get_collection(
- hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
- )[OneLevelIndex][TwoLevelIndex][ThreeLevelIndex][FourLevelIndex]
- d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][
- 22
- ]
+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex]
+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex][TwoLevelIndex][
+ ThreeLevelIndex
+ ][
+ FourLevelIndex
+ ]
d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][
22
]
- assignment = (
- some.rather.elaborate.rule() and another.rule.ending_with.index[123]
- )
-
- def easy_asserts(self) -> None:
+ assignment = NOT_IMPLEMENTED_call() and another.rule.ending_with.index[123]
def easy_asserts(self) -> None:
- assert {
- key1: value1,
- key2: value2,
@ -267,7 +282,8 @@ class C:
- key8: value8,
- key9: value9,
- } == expected, "Not what we expected"
-
+ NOT_YET_IMPLEMENTED_StmtAssert
- assert expected == {
- key1: value1,
- key2: value2,
@ -279,7 +295,8 @@ class C:
- key8: value8,
- key9: value9,
- }, "Not what we expected"
-
+ NOT_YET_IMPLEMENTED_StmtAssert
- assert expected == {
- key1: value1,
- key2: value2,
@ -291,8 +308,9 @@ class C:
- key8: value8,
- key9: value9,
- }
-
- def tricky_asserts(self) -> None:
+ NOT_YET_IMPLEMENTED_StmtAssert
def tricky_asserts(self) -> None:
- assert {
- key1: value1,
- key2: value2,
@ -306,7 +324,8 @@ class C:
- } == expected(
- value, is_going_to_be="too long to fit in a single line", srsly=True
- ), "Not what we expected"
-
+ NOT_YET_IMPLEMENTED_StmtAssert
- assert {
- key1: value1,
- key2: value2,
@ -320,7 +339,8 @@ class C:
- } == expected, (
- "Not what we expected and the message is too long to fit in one line"
- )
-
+ NOT_YET_IMPLEMENTED_StmtAssert
- assert expected(
- value, is_going_to_be="too long to fit in a single line", srsly=True
- ) == {
@ -334,7 +354,8 @@ class C:
- key8: value8,
- key9: value9,
- }, "Not what we expected"
-
+ NOT_YET_IMPLEMENTED_StmtAssert
- assert expected == {
- key1: value1,
- key2: value2,
@ -349,7 +370,8 @@ class C:
- "Not what we expected and the message is too long to fit in one line"
- " because it's too long"
- )
-
+ NOT_YET_IMPLEMENTED_StmtAssert
- dis_c_instance_method = """\
- %3d 0 LOAD_FAST 1 (x)
- 2 LOAD_CONST 1 (1)
@ -360,8 +382,11 @@ class C:
- 12 RETURN_VALUE
- """ % (
- _C.__init__.__code__.co_firstlineno + 1,
- )
-
+ dis_c_instance_method = "NOT_YET_IMPLEMENTED_STRING" % (
+ _C.__init__.__code__.co_firstlineno
+ + 1,
)
- assert (
- expectedexpectedexpectedexpectedexpectedexpectedexpectedexpectedexpect
- == {
@ -376,13 +401,58 @@ class C:
- key9: value9,
- }
- )
+NOT_YET_IMPLEMENTED_StmtClassDef
+ NOT_YET_IMPLEMENTED_StmtAssert
```
## Ruff Output
```py
NOT_YET_IMPLEMENTED_StmtClassDef
class C:
def test(self) -> None:
NOT_YET_IMPLEMENTED_StmtWith
xxxxxxxxxxxxxxxx = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
return "NOT_YET_IMPLEMENTED_STRING" % (
test.name,
test.filename,
lineno,
lname,
err,
)
def omitting_trailers(self) -> None:
NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex]
NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex][TwoLevelIndex][
ThreeLevelIndex
][
FourLevelIndex
]
d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][
22
]
assignment = NOT_IMPLEMENTED_call() and another.rule.ending_with.index[123]
def easy_asserts(self) -> None:
NOT_YET_IMPLEMENTED_StmtAssert
NOT_YET_IMPLEMENTED_StmtAssert
NOT_YET_IMPLEMENTED_StmtAssert
def tricky_asserts(self) -> None:
NOT_YET_IMPLEMENTED_StmtAssert
NOT_YET_IMPLEMENTED_StmtAssert
NOT_YET_IMPLEMENTED_StmtAssert
NOT_YET_IMPLEMENTED_StmtAssert
dis_c_instance_method = "NOT_YET_IMPLEMENTED_STRING" % (
_C.__init__.__code__.co_firstlineno
+ 1,
)
NOT_YET_IMPLEMENTED_StmtAssert
```
## Black Output

View file

@ -194,9 +194,9 @@ class C:
```diff
--- Black
+++ Ruff
@@ -1,181 +1 @@
-class C:
- def test(self) -> None:
@@ -1,181 +1,46 @@
class C:
def test(self) -> None:
- with patch("black.out", print):
- self.assertEqual(
- unstyle(str(report)), "1 file reformatted, 1 file failed to reformat."
@ -239,23 +239,38 @@ class C:
- return (
- 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
- % (test.name, test.filename, lineno, lname, err)
- )
-
- def omitting_trailers(self) -> None:
+ NOT_YET_IMPLEMENTED_StmtWith
+ xxxxxxxxxxxxxxxx = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
+ return "NOT_YET_IMPLEMENTED_STRING" % (
+ test.name,
+ test.filename,
+ lineno,
+ lname,
+ err,
)
def omitting_trailers(self) -> None:
- get_collection(
- hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
- )[OneLevelIndex]
- get_collection(
- hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
- )[OneLevelIndex][TwoLevelIndex][ThreeLevelIndex][FourLevelIndex]
- d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][
- 22
- ]
+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex]
+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex][TwoLevelIndex][
+ ThreeLevelIndex
+ ][
+ FourLevelIndex
+ ]
d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][
22
]
- assignment = (
- some.rather.elaborate.rule() and another.rule.ending_with.index[123]
- )
-
- def easy_asserts(self) -> None:
+ assignment = NOT_IMPLEMENTED_call() and another.rule.ending_with.index[123]
def easy_asserts(self) -> None:
- assert {
- key1: value1,
- key2: value2,
@ -267,7 +282,8 @@ class C:
- key8: value8,
- key9: value9,
- } == expected, "Not what we expected"
-
+ NOT_YET_IMPLEMENTED_StmtAssert
- assert expected == {
- key1: value1,
- key2: value2,
@ -279,7 +295,8 @@ class C:
- key8: value8,
- key9: value9,
- }, "Not what we expected"
-
+ NOT_YET_IMPLEMENTED_StmtAssert
- assert expected == {
- key1: value1,
- key2: value2,
@ -291,8 +308,9 @@ class C:
- key8: value8,
- key9: value9,
- }
-
- def tricky_asserts(self) -> None:
+ NOT_YET_IMPLEMENTED_StmtAssert
def tricky_asserts(self) -> None:
- assert {
- key1: value1,
- key2: value2,
@ -306,7 +324,8 @@ class C:
- } == expected(
- value, is_going_to_be="too long to fit in a single line", srsly=True
- ), "Not what we expected"
-
+ NOT_YET_IMPLEMENTED_StmtAssert
- assert {
- key1: value1,
- key2: value2,
@ -320,7 +339,8 @@ class C:
- } == expected, (
- "Not what we expected and the message is too long to fit in one line"
- )
-
+ NOT_YET_IMPLEMENTED_StmtAssert
- assert expected(
- value, is_going_to_be="too long to fit in a single line", srsly=True
- ) == {
@ -334,7 +354,8 @@ class C:
- key8: value8,
- key9: value9,
- }, "Not what we expected"
-
+ NOT_YET_IMPLEMENTED_StmtAssert
- assert expected == {
- key1: value1,
- key2: value2,
@ -349,7 +370,8 @@ class C:
- "Not what we expected and the message is too long to fit in one line"
- " because it's too long"
- )
-
+ NOT_YET_IMPLEMENTED_StmtAssert
- dis_c_instance_method = """\
- %3d 0 LOAD_FAST 1 (x)
- 2 LOAD_CONST 1 (1)
@ -360,8 +382,11 @@ class C:
- 12 RETURN_VALUE
- """ % (
- _C.__init__.__code__.co_firstlineno + 1,
- )
-
+ dis_c_instance_method = "NOT_YET_IMPLEMENTED_STRING" % (
+ _C.__init__.__code__.co_firstlineno
+ + 1,
)
- assert (
- expectedexpectedexpectedexpectedexpectedexpectedexpectedexpectedexpect
- == {
@ -376,13 +401,58 @@ class C:
- key9: value9,
- }
- )
+NOT_YET_IMPLEMENTED_StmtClassDef
+ NOT_YET_IMPLEMENTED_StmtAssert
```
## Ruff Output
```py
NOT_YET_IMPLEMENTED_StmtClassDef
class C:
def test(self) -> None:
NOT_YET_IMPLEMENTED_StmtWith
xxxxxxxxxxxxxxxx = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
return "NOT_YET_IMPLEMENTED_STRING" % (
test.name,
test.filename,
lineno,
lname,
err,
)
def omitting_trailers(self) -> None:
NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex]
NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex][TwoLevelIndex][
ThreeLevelIndex
][
FourLevelIndex
]
d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][
22
]
assignment = NOT_IMPLEMENTED_call() and another.rule.ending_with.index[123]
def easy_asserts(self) -> None:
NOT_YET_IMPLEMENTED_StmtAssert
NOT_YET_IMPLEMENTED_StmtAssert
NOT_YET_IMPLEMENTED_StmtAssert
def tricky_asserts(self) -> None:
NOT_YET_IMPLEMENTED_StmtAssert
NOT_YET_IMPLEMENTED_StmtAssert
NOT_YET_IMPLEMENTED_StmtAssert
NOT_YET_IMPLEMENTED_StmtAssert
dis_c_instance_method = "NOT_YET_IMPLEMENTED_STRING" % (
_C.__init__.__code__.co_firstlineno
+ 1,
)
NOT_YET_IMPLEMENTED_StmtAssert
```
## Black Output

View file

@ -17,12 +17,12 @@ class ClassWithDocstring:
```diff
--- Black
+++ Ruff
@@ -1,4 +1,3 @@
@@ -1,4 +1,4 @@
# Make sure when the file ends with class's docstring,
# It doesn't add extra blank lines.
-class ClassWithDocstring:
class ClassWithDocstring:
- """A docstring."""
+NOT_YET_IMPLEMENTED_StmtClassDef
+ "NOT_YET_IMPLEMENTED_STRING"
```
## Ruff Output
@ -30,7 +30,8 @@ class ClassWithDocstring:
```py
# Make sure when the file ends with class's docstring,
# It doesn't add extra blank lines.
NOT_YET_IMPLEMENTED_StmtClassDef
class ClassWithDocstring:
"NOT_YET_IMPLEMENTED_STRING"
```
## Black Output

View file

@ -234,18 +234,19 @@ def stable_quote_normalization_with_immediate_inner_single_quote(self):
```diff
--- Black
+++ Ruff
@@ -1,219 +1,149 @@
-class MyClass:
@@ -1,219 +1,154 @@
class MyClass:
- """Multiline
- class docstring
- """
-
- def method(self):
+ "NOT_YET_IMPLEMENTED_STRING"
def method(self):
- """Multiline
- method docstring
- """
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
+ "NOT_YET_IMPLEMENTED_STRING"
pass
def foo():
@ -396,12 +397,12 @@ def stable_quote_normalization_with_immediate_inner_single_quote(self):
- tab at start of line and then a tab separated value
- multiple tabs at the beginning and inline
- mixed tabs and spaces at beginning. next line has mixed tabs and spaces only.
-
- line ends with some tabs
- """
+ "NOT_YET_IMPLEMENTED_STRING"
- line ends with some tabs
- """
-
def docstring_with_inline_tabs_and_tab_indentation():
- """hey
-
@ -494,7 +495,12 @@ def stable_quote_normalization_with_immediate_inner_single_quote(self):
## Ruff Output
```py
NOT_YET_IMPLEMENTED_StmtClassDef
class MyClass:
"NOT_YET_IMPLEMENTED_STRING"
def method(self):
"NOT_YET_IMPLEMENTED_STRING"
pass
def foo():

View file

@ -134,7 +134,7 @@ elif unformatted:
return True
# yapf: enable
elif b:
@@ -39,49 +21,29 @@
@@ -39,12 +21,12 @@
# Regression test for https://github.com/psf/black/issues/2567.
if True:
# fmt: off
@ -152,40 +152,44 @@ elif unformatted:
# Regression test for https://github.com/psf/black/issues/3184.
-class A:
- async def call(param):
- if param:
- # fmt: off
@@ -52,29 +34,27 @@
async def call(param):
if param:
# fmt: off
- if param[0:4] in (
- "ABCD", "EFGH"
- ) :
- # fmt: on
+ if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right:
# fmt: on
- print ( "This won't be formatted" )
-
+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
- elif param[0:4] in ("ZZZZ",):
- print ( "This won't be formatted either" )
-
+ elif NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right:
+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
- print("This will be formatted")
+NOT_YET_IMPLEMENTED_StmtClassDef
+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
# Regression test for https://github.com/psf/black/issues/2985.
-class Named(t.Protocol):
- # fmt: off
- @property
class Named(t.Protocol):
# fmt: off
@property
- def this_wont_be_formatted ( self ) -> str: ...
+NOT_YET_IMPLEMENTED_StmtClassDef
+ def this_wont_be_formatted(self) -> str:
+ ...
-class Factory(t.Protocol):
- def this_will_be_formatted(self, **kwargs) -> Named:
- ...
class Factory(t.Protocol):
def this_will_be_formatted(self, **kwargs) -> Named:
...
-
- # fmt: on
+NOT_YET_IMPLEMENTED_StmtClassDef
# fmt: on
# Regression test for https://github.com/psf/black/issues/3436.
@@ -82,6 +62,6 @@
if x:
return x
# fmt: off
@ -231,14 +235,32 @@ else:
# Regression test for https://github.com/psf/black/issues/3184.
NOT_YET_IMPLEMENTED_StmtClassDef
class A:
async def call(param):
if param:
# fmt: off
if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right:
# fmt: on
NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
elif NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right:
NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
# Regression test for https://github.com/psf/black/issues/2985.
NOT_YET_IMPLEMENTED_StmtClassDef
class Named(t.Protocol):
# fmt: off
@property
def this_wont_be_formatted(self) -> str:
...
NOT_YET_IMPLEMENTED_StmtClassDef
class Factory(t.Protocol):
def this_will_be_formatted(self, **kwargs) -> Named:
...
# fmt: on
# Regression test for https://github.com/psf/black/issues/3436.

View file

@ -18,19 +18,23 @@ class A:
```diff
--- Black
+++ Ruff
@@ -1,5 +1 @@
-class A:
- def f(self):
@@ -1,5 +1,5 @@
class A:
def f(self):
- for line in range(10):
- if True:
- pass # fmt: skip
+NOT_YET_IMPLEMENTED_StmtClassDef
+ for line in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg):
if True:
pass # fmt: skip
```
## Ruff Output
```py
NOT_YET_IMPLEMENTED_StmtClassDef
class A:
def f(self):
for line in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg):
if True:
pass # fmt: skip
```
## Black Output

View file

@ -75,7 +75,7 @@ async def test_async_with():
```diff
--- Black
+++ Ruff
@@ -1,62 +1,47 @@
@@ -1,62 +1,54 @@
# Make sure a leading comment is not removed.
-def some_func( unformatted, args ): # fmt: skip
- print("I am some_func")
@ -98,14 +98,19 @@ async def test_async_with():
-class SomeClass( Unformatted, SuperClasses ): # fmt: skip
- def some_method( self, unformatted, args ): # fmt: skip
- print("I am some_method")
- return 0
+NOT_YET_IMPLEMENTED_StmtClassDef
+class SomeClass(Unformatted, SuperClasses): # fmt: skip
+ def some_method(self, unformatted, args): # fmt: skip
+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
return 0
- async def some_async_method( self, unformatted, args ): # fmt: skip
- print("I am some_async_method")
- await asyncio.sleep(1)
+ async def some_async_method(self, unformatted, args): # fmt: skip
+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
+ await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
-
# Make sure a leading comment is not removed.
-if unformatted_call( args ): # fmt: skip
- print("First branch")
@ -177,7 +182,14 @@ async def some_async_func(unformatted, args): # fmt: skip
# Make sure a leading comment is not removed.
NOT_YET_IMPLEMENTED_StmtClassDef
class SomeClass(Unformatted, SuperClasses): # fmt: skip
def some_method(self, unformatted, args): # fmt: skip
NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
return 0
async def some_async_method(self, unformatted, args): # fmt: skip
NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
# Make sure a leading comment is not removed.

View file

@ -66,7 +66,7 @@ with hmm_but_this_should_get_two_preceding_newlines():
```diff
--- Black
+++ Ruff
@@ -2,64 +2,39 @@
@@ -2,64 +2,41 @@
a,
**kwargs,
) -> A:
@ -129,17 +129,17 @@ with hmm_but_this_should_get_two_preceding_newlines():
elif False:
-
- class IHopeYouAreHavingALovelyDay:
- def __call__(self):
class IHopeYouAreHavingALovelyDay:
def __call__(self):
- print("i_should_be_followed_by_only_one_newline")
-
+ NOT_YET_IMPLEMENTED_StmtClassDef
+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
else:
-
def foo():
pass
-
-with hmm_but_this_should_get_two_preceding_newlines():
- pass
+NOT_YET_IMPLEMENTED_StmtWith
@ -182,7 +182,9 @@ elif NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right:
NOT_YET_IMPLEMENTED_StmtTry
elif False:
NOT_YET_IMPLEMENTED_StmtClassDef
class IHopeYouAreHavingALovelyDay:
def __call__(self):
NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
else:
def foo():
pass

View file

@ -121,7 +121,7 @@ with open("/path/to/file.txt", mode="r") as read_file:
```diff
--- Black
+++ Ruff
@@ -1,78 +1,72 @@
@@ -1,78 +1,74 @@
-import random
+NOT_YET_IMPLEMENTED_StmtImport
@ -151,10 +151,10 @@ with open("/path/to/file.txt", mode="r") as read_file:
+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
-class Foo:
- def bar(self):
class Foo:
def bar(self):
- print("The newline above me should be deleted!")
+NOT_YET_IMPLEMENTED_StmtClassDef
+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
-for i in range(5):
@ -255,7 +255,9 @@ def foo4():
NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
NOT_YET_IMPLEMENTED_StmtClassDef
class Foo:
def bar(self):
NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg):

View file

@ -42,7 +42,7 @@ assert (
```diff
--- Black
+++ Ruff
@@ -2,57 +2,24 @@
@@ -2,20 +2,10 @@
(
()
<< 0
@ -65,16 +65,16 @@ assert (
importA
0
0 ^ 0 #
@@ -24,35 +14,15 @@
-class A:
- def foo(self):
class A:
def foo(self):
- for _ in range(10):
- aaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbb.cccccccccc(
- xxxxxxxxxxxx
- ) # pylint: disable=no-member
+NOT_YET_IMPLEMENTED_StmtClassDef
+ for _ in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg):
+ aaaaaaaaaaaaaaaaaaa = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
def test(self, othr):
@ -126,7 +126,10 @@ importA
0 ^ 0 #
NOT_YET_IMPLEMENTED_StmtClassDef
class A:
def foo(self):
for _ in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg):
aaaaaaaaaaaaaaaaaaa = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)
def test(self, othr):

View file

@ -38,7 +38,7 @@ class A:
```diff
--- Black
+++ Ruff
@@ -1,34 +1,15 @@
@@ -1,34 +1,25 @@
-if e1234123412341234.winerror not in (
- _winapi.ERROR_SEM_TIMEOUT,
- _winapi.ERROR_PIPE_BUSY,
@ -61,25 +61,30 @@ class A:
+ new_id = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + 1
-class X:
- def get_help_text(self):
class X:
def get_help_text(self):
- return ngettext(
- "Your password must contain at least %(min_length)d character.",
- "Your password must contain at least %(min_length)d characters.",
- self.min_length,
- ) % {"min_length": self.min_length}
+NOT_YET_IMPLEMENTED_StmtClassDef
+ return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) % {
+ "NOT_YET_IMPLEMENTED_STRING": self.min_length,
+ }
-class A:
- def b(self):
class A:
def b(self):
- if self.connection.mysql_is_mariadb and (
- 10,
- 4,
- 3,
- ) < self.connection.mysql_version < (10, 5, 2):
- pass
+NOT_YET_IMPLEMENTED_StmtClassDef
+ if (
+ self.connection.mysql_is_mariadb
+ and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
+ ):
pass
```
## Ruff Output
@ -96,10 +101,20 @@ if x:
new_id = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + 1
NOT_YET_IMPLEMENTED_StmtClassDef
class X:
def get_help_text(self):
return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) % {
"NOT_YET_IMPLEMENTED_STRING": self.min_length,
}
NOT_YET_IMPLEMENTED_StmtClassDef
class A:
def b(self):
if (
self.connection.mysql_is_mariadb
and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
):
pass
```
## Black Output

View file

@ -0,0 +1,97 @@
---
source: crates/ruff_python_formatter/src/lib.rs
expression: snapshot
---
## Input
```py
class Test(
Aaaaaaaaaaaaaaaaa,
Bbbbbbbbbbbbbbbb,
DDDDDDDDDDDDDDDD,
EEEEEEEEEEEEEE,
metaclass=meta,
):
pass
class Test((Aaaaaaaaaaaaaaaaa), Bbbbbbbbbbbbbbbb, metaclass=meta):
pass
class Test( # trailing class comment
Aaaaaaaaaaaaaaaaa, # trailing comment
# in between comment
Bbbbbbbbbbbbbbbb,
# another leading comment
DDDDDDDDDDDDDDDD,
EEEEEEEEEEEEEE,
# meta comment
metaclass=meta, # trailing meta comment
):
pass
class Test((Aaaa)):
...
class Test(aaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccccccccccc + dddddddddddddddddddddd + eeeeeeeee, ffffffffffffffffff, gggggggggggggggggg):
pass
class Test(Aaaa): # trailing comment
pass
```
## Output
```py
class Test(
Aaaaaaaaaaaaaaaaa,
Bbbbbbbbbbbbbbbb,
DDDDDDDDDDDDDDDD,
EEEEEEEEEEEEEE,
metaclass=meta,
):
pass
class Test((Aaaaaaaaaaaaaaaaa), Bbbbbbbbbbbbbbbb, metaclass=meta):
pass
class Test(
# trailing class comment
Aaaaaaaaaaaaaaaaa, # trailing comment
# in between comment
Bbbbbbbbbbbbbbbb,
# another leading comment
DDDDDDDDDDDDDDDD,
EEEEEEEEEEEEEE,
# meta comment
metaclass=meta, # trailing meta comment
):
pass
class Test((Aaaa)):
...
class Test(
aaaaaaaaaaaaaaa
+ bbbbbbbbbbbbbbbbbbbbbb
+ cccccccccccccccccccccccc
+ dddddddddddddddddddddd
+ eeeeeeeee,
ffffffffffffffffff,
gggggggggggggggggg,
):
pass
class Test(Aaaa): # trailing comment
pass
```

View file

@ -52,7 +52,10 @@ b = 20
# Adds two lines after `b`
NOT_YET_IMPLEMENTED_StmtClassDef
class Test:
def a(self):
pass
# trailing comment
# two lines before, one line after

View file

@ -1,12 +1,138 @@
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult};
use rustpython_parser::ast::StmtClassDef;
use crate::comments::trailing_comments;
use crate::expression::parentheses::Parenthesize;
use crate::prelude::*;
use crate::trivia::{first_non_trivia_token, SimpleTokenizer, Token, TokenKind};
use crate::USE_MAGIC_TRAILING_COMMA;
use ruff_formatter::{format_args, write};
use ruff_text_size::TextRange;
use rustpython_parser::ast::{Expr, Keyword, Ranged, StmtClassDef};
#[derive(Default)]
pub struct FormatStmtClassDef;
impl FormatNodeRule<StmtClassDef> for FormatStmtClassDef {
fn fmt_fields(&self, item: &StmtClassDef, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [not_yet_implemented(item)])
let StmtClassDef {
range: _,
name,
bases,
keywords,
body,
decorator_list,
} = item;
f.join_with(hard_line_break())
.entries(decorator_list.iter().formatted())
.finish()?;
if !decorator_list.is_empty() {
hard_line_break().fmt(f)?;
}
write!(f, [text("class"), space(), name.format()])?;
if !(bases.is_empty() && keywords.is_empty()) {
write!(
f,
[group(&format_args![
text("("),
soft_block_indent(&FormatInheritanceClause {
class_definition: item
}),
text(")")
])]
)?;
}
let comments = f.context().comments().clone();
let trailing_head_comments = comments.dangling_comments(item);
write!(
f,
[
text(":"),
trailing_comments(trailing_head_comments),
block_indent(&body.format())
]
)
}
fn fmt_dangling_comments(
&self,
_node: &StmtClassDef,
_f: &mut PyFormatter,
) -> FormatResult<()> {
// handled in fmt_fields
Ok(())
}
}
struct FormatInheritanceClause<'a> {
class_definition: &'a StmtClassDef,
}
impl Format<PyFormatContext<'_>> for FormatInheritanceClause<'_> {
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
let StmtClassDef {
bases,
keywords,
name,
..
} = self.class_definition;
let separator = format_with(|f| write!(f, [text(","), soft_line_break_or_space()]));
let source = f.context().contents();
let mut joiner = f.join_with(&separator);
if let Some((first, rest)) = bases.split_first() {
// Manually handle parentheses for the first expression because the logic in `FormatExpr`
// doesn't know that it should disregard the parentheses of the inheritance clause.
// ```python
// class Test(A) # A is not parenthesized, the parentheses belong to the inheritance clause
// class Test((A)) # A is parenthesized
// ```
// parentheses from the inheritance clause belong to the expression.
let tokenizer = SimpleTokenizer::new(source, TextRange::new(name.end(), first.start()))
.skip_trivia();
let left_paren_count = tokenizer
.take_while(|token| token.kind() == TokenKind::LParen)
.count();
// Ignore the first parentheses count
let parenthesize = if left_paren_count > 1 {
Parenthesize::Always
} else {
Parenthesize::Never
};
joiner.entry(&first.format().with_options(parenthesize));
joiner.entries(rest.iter().formatted());
}
joiner.entries(keywords.iter().formatted()).finish()?;
if_group_breaks(&text(",")).fmt(f)?;
if USE_MAGIC_TRAILING_COMMA {
let last_end = keywords
.last()
.map(Keyword::end)
.or_else(|| bases.last().map(Expr::end))
.unwrap();
if matches!(
first_non_trivia_token(last_end, f.context().contents()),
Some(Token {
kind: TokenKind::Comma,
..
})
) {
hard_line_break().fmt(f)?;
}
}
Ok(())
}
}

View file

@ -252,7 +252,8 @@ one_leading_newline = 10
no_leading_newline = 30
NOT_YET_IMPLEMENTED_StmtClassDef
class InTheMiddle:
pass
trailing_statement = 1
@ -283,7 +284,8 @@ two_leading_newlines = 20
one_leading_newline = 10
no_leading_newline = 30
NOT_YET_IMPLEMENTED_StmtClassDef
class InTheMiddle:
pass
trailing_statement = 1