diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/attribute.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/attribute.py new file mode 100644 index 0000000000000..bdc18f4696c67 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/attribute.py @@ -0,0 +1,29 @@ +( + a + # comment + .b # trailing comment +) + +( + a + # comment + .b # trailing dot comment # trailing identifier comment +) + +( + a + # comment + .b # trailing identifier comment +) + + +( + a + # comment + . # trailing dot comment + # in between + b # trailing identifier comment +) + + +aaaaaaaaaaaaaaaaaaaaa.lllllllllllllllllllllllllllloooooooooong.chaaaaaaaaaaaaaaaaaaaaaaiiiiiiiiiiiiiiiiiiiiiiinnnnnnnn.ooooooooooooooooooooooooofffffffff.aaaaaaaaaattr diff --git a/crates/ruff_python_formatter/src/comments/placement.rs b/crates/ruff_python_formatter/src/comments/placement.rs index 97502a7e67369..5d09f24592715 100644 --- a/crates/ruff_python_formatter/src/comments/placement.rs +++ b/crates/ruff_python_formatter/src/comments/placement.rs @@ -31,6 +31,7 @@ pub(super) fn place_comment<'a>( handle_leading_function_with_decorators_comment, handle_dict_unpacking_comment, handle_slice_comments, + handle_attribute_comment, ]; for handler in HANDLERS { comment = match handler(comment, locator) { @@ -1005,6 +1006,43 @@ fn handle_dict_unpacking_comment<'a>( CommentPlacement::Default(comment) } +// Own line comments coming after the node are always dangling comments +// ```python +// ( +// a +// # trailing a comment +// . # dangling comment +// # or this +// b +// ) +// ``` +fn handle_attribute_comment<'a>( + comment: DecoratedComment<'a>, + locator: &Locator, +) -> CommentPlacement<'a> { + let Some(attribute) = comment.enclosing_node().expr_attribute() else { + return CommentPlacement::Default(comment); + }; + + // It must be a comment AFTER the name + if comment.preceding_node().is_none() { + return CommentPlacement::Default(comment); + } + + let between_value_and_attr = TextRange::new(attribute.value.end(), attribute.attr.start()); + + let dot = SimpleTokenizer::new(locator.contents(), between_value_and_attr) + .skip_trivia() + .next() + .expect("Expected the `.` character after the value"); + + if TextRange::new(dot.end(), attribute.attr.start()).contains(comment.slice().start()) { + CommentPlacement::dangling(attribute.into(), comment) + } else { + CommentPlacement::Default(comment) + } +} + /// Returns `true` if `right` is `Some` and `left` and `right` are referentially equal. fn are_same_optional<'a, T>(left: AnyNodeRef, right: Option) -> bool where diff --git a/crates/ruff_python_formatter/src/expression/expr_attribute.rs b/crates/ruff_python_formatter/src/expression/expr_attribute.rs index 9732025e3563b..fd43e9f20a56e 100644 --- a/crates/ruff_python_formatter/src/expression/expr_attribute.rs +++ b/crates/ruff_python_formatter/src/expression/expr_attribute.rs @@ -1,9 +1,9 @@ -use crate::comments::Comments; +use crate::comments::{leading_comments, trailing_comments, Comments}; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; use crate::prelude::*; -use crate::{not_yet_implemented_custom_text, FormatNodeRule}; +use crate::FormatNodeRule; use ruff_formatter::write; use rustpython_parser::ast::{Constant, Expr, ExprAttribute, ExprConstant}; @@ -15,11 +15,11 @@ impl FormatNodeRule for FormatExprAttribute { let ExprAttribute { value, range: _, - attr: _, + attr, ctx: _, } = item; - let requires_space = matches!( + let needs_parentheses = matches!( value.as_ref(), Expr::Constant(ExprConstant { value: Constant::Int(_) | Constant::Float(_), @@ -27,16 +27,45 @@ impl FormatNodeRule for FormatExprAttribute { }) ); + if needs_parentheses { + value.format().with_options(Parenthesize::Always).fmt(f)?; + } else { + value.format().fmt(f)?; + } + + let comments = f.context().comments().clone(); + + if comments.has_trailing_own_line_comments(value.as_ref()) { + hard_line_break().fmt(f)?; + } + + let dangling_comments = comments.dangling_comments(item); + + let leading_attribute_comments_start = + dangling_comments.partition_point(|comment| comment.line_position().is_end_of_line()); + let (trailing_dot_comments, leading_attribute_comments) = + dangling_comments.split_at(leading_attribute_comments_start); + write!( f, [ - item.value.format(), - requires_space.then_some(space()), text("."), - not_yet_implemented_custom_text("NOT_IMPLEMENTED_attr") + trailing_comments(trailing_dot_comments), + (!leading_attribute_comments.is_empty()).then_some(hard_line_break()), + leading_comments(leading_attribute_comments), + attr.format() ] ) } + + fn fmt_dangling_comments( + &self, + _node: &ExprAttribute, + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // handle in `fmt_fields` + Ok(()) + } } impl NeedsParentheses for ExprAttribute { @@ -46,6 +75,9 @@ impl NeedsParentheses for ExprAttribute { source: &str, comments: &Comments, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + Parentheses::Optional => Parentheses::Never, + parentheses => parentheses, + } } } diff --git a/crates/ruff_python_formatter/src/expression/parentheses.rs b/crates/ruff_python_formatter/src/expression/parentheses.rs index 7d57fe9df330f..d1506bd518a49 100644 --- a/crates/ruff_python_formatter/src/expression/parentheses.rs +++ b/crates/ruff_python_formatter/src/expression/parentheses.rs @@ -23,8 +23,12 @@ pub(super) fn default_expression_needs_parentheses( "Should only be called for expressions" ); + #[allow(clippy::if_same_then_else)] + if parenthesize.is_always() { + Parentheses::Always + } // `Optional` or `Preserve` and expression has parentheses in source code. - if !parenthesize.is_if_breaks() && is_expression_parenthesized(node, source) { + else if !parenthesize.is_if_breaks() && is_expression_parenthesized(node, source) { Parentheses::Always } // `Optional` or `IfBreaks`: Add parentheses if the expression doesn't fit on a line but enforce @@ -53,9 +57,15 @@ pub enum Parenthesize { /// Parenthesizes the expression only if it doesn't fit on a line. IfBreaks, + + Always, } impl Parenthesize { + pub(crate) const fn is_always(self) -> bool { + matches!(self, Parenthesize::Always) + } + pub(crate) const fn is_if_breaks(self) -> bool { matches!(self, Parenthesize::IfBreaks) } @@ -70,7 +80,8 @@ impl Parenthesize { /// whether there are parentheses in the source code or not. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Parentheses { - /// Always create parentheses + /// Always set parentheses regardless if the expression breaks or if they were + /// present in the source. Always, /// Only add parentheses when necessary because the expression breaks over multiple lines. diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__attribute_access_on_number_literals_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__attribute_access_on_number_literals_py.snap index da19ad12f548d..72a7fd2ecd02c 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__attribute_access_on_number_literals_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__attribute_access_on_number_literals_py.snap @@ -55,22 +55,21 @@ y = 100(no) +x = NOT_IMPLEMENTED_call() +x = NOT_IMPLEMENTED_call() +x = NOT_IMPLEMENTED_call() -+x = 1. .NOT_IMPLEMENTED_attr -+x = 1E+1 .NOT_IMPLEMENTED_attr -+x = 1E-1 .NOT_IMPLEMENTED_attr ++x = (1.).imag ++x = (1E+1).imag ++x = (1E-1).real +x = NOT_IMPLEMENTED_call() -+x = 123456789.123456789E123456789 .NOT_IMPLEMENTED_attr ++x = (123456789.123456789E123456789).real +x = NOT_IMPLEMENTED_call() -+x = 123456789J.NOT_IMPLEMENTED_attr ++x = 123456789J.real +x = NOT_IMPLEMENTED_call() +x = NOT_IMPLEMENTED_call() +x = NOT_IMPLEMENTED_call() -+x = 0O777 .NOT_IMPLEMENTED_attr ++x = (0O777).real +x = NOT_IMPLEMENTED_call() +x = -100.0000J --if (10).real: -+if 10 .NOT_IMPLEMENTED_attr: + if (10).real: ... y = 100[no] @@ -84,21 +83,21 @@ y = 100(no) x = NOT_IMPLEMENTED_call() x = NOT_IMPLEMENTED_call() x = NOT_IMPLEMENTED_call() -x = 1. .NOT_IMPLEMENTED_attr -x = 1E+1 .NOT_IMPLEMENTED_attr -x = 1E-1 .NOT_IMPLEMENTED_attr +x = (1.).imag +x = (1E+1).imag +x = (1E-1).real x = NOT_IMPLEMENTED_call() -x = 123456789.123456789E123456789 .NOT_IMPLEMENTED_attr +x = (123456789.123456789E123456789).real x = NOT_IMPLEMENTED_call() -x = 123456789J.NOT_IMPLEMENTED_attr +x = 123456789J.real x = NOT_IMPLEMENTED_call() x = NOT_IMPLEMENTED_call() x = NOT_IMPLEMENTED_call() -x = 0O777 .NOT_IMPLEMENTED_attr +x = (0O777).real x = NOT_IMPLEMENTED_call() x = -100.0000J -if 10 .NOT_IMPLEMENTED_attr: +if (10).real: ... y = 100[no] diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__collections_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__collections_py.snap index 0c369db6d66d3..b567509488463 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__collections_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__collections_py.snap @@ -165,7 +165,7 @@ if True: # looping over a 1-tuple should also not get wrapped for x in (1,): -@@ -63,37 +42,17 @@ +@@ -63,14 +42,10 @@ for (x,) in (1,), (2,), (3,): pass @@ -181,13 +181,9 @@ if True: +NOT_IMPLEMENTED_call() if True: -- IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = ( -- Config.IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING -- | {pylons.controllers.WSGIController} -- ) -+ IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = Config.NOT_IMPLEMENTED_attr | { -+ pylons.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr, -+ } + IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = ( +@@ -79,21 +54,6 @@ + ) if True: - ec2client.get_waiter("instance_stopped").wait( @@ -266,9 +262,10 @@ division_result_tuple = (6 / 2,) NOT_IMPLEMENTED_call() if True: - IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = Config.NOT_IMPLEMENTED_attr | { - pylons.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr, - } + IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = ( + Config.IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING + | {pylons.controllers.WSGIController} + ) if True: NOT_IMPLEMENTED_call() diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments2_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments2_py.snap index db67f3dc39c91..42acde710af31 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments2_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments2_py.snap @@ -227,7 +227,7 @@ instruction()#comment with bad spacing ] not_shareables = [ -@@ -37,49 +33,57 @@ +@@ -37,31 +33,35 @@ # builtin types and objects type, object, @@ -263,31 +263,24 @@ instruction()#comment with bad spacing def inline_comments_in_brackets_ruin_everything(): if typedargslist: - parameters.children = [children[0], body, children[-1]] # (1 # )1 -- parameters.children = [ -+ parameters.NOT_IMPLEMENTED_attr = [ + parameters.children = [ + children[0], # (1 + body, + children[-1], # )1 + ] -+ parameters.NOT_IMPLEMENTED_attr = [ ++ parameters.children = [ children[0], body, children[-1], # type: ignore - ] - else: -- parameters.children = [ -- parameters.children[0], # (2 what if this was actually long -+ parameters.NOT_IMPLEMENTED_attr = [ -+ parameters.NOT_IMPLEMENTED_attr[0], # (2 what if this was actually long +@@ -72,14 +72,18 @@ body, -- parameters.children[-1], # )2 -+ parameters.NOT_IMPLEMENTED_attr[-1], # )2 + parameters.children[-1], # )2 ] - parameters.children = [parameters.what_if_this_was_actually_long.children[0], body, parameters.children[-1]] # type: ignore -+ parameters.NOT_IMPLEMENTED_attr = [ -+ parameters.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr[0], ++ parameters.children = [ ++ parameters.what_if_this_was_actually_long.children[0], + body, -+ parameters.NOT_IMPLEMENTED_attr[-1], ++ parameters.children[-1], + ] # type: ignore if ( - self._proc is not None @@ -457,26 +450,26 @@ else: # Comment before function. def inline_comments_in_brackets_ruin_everything(): if typedargslist: - parameters.NOT_IMPLEMENTED_attr = [ + parameters.children = [ children[0], # (1 body, children[-1], # )1 ] - parameters.NOT_IMPLEMENTED_attr = [ + parameters.children = [ children[0], body, children[-1], # type: ignore ] else: - parameters.NOT_IMPLEMENTED_attr = [ - parameters.NOT_IMPLEMENTED_attr[0], # (2 what if this was actually long + parameters.children = [ + parameters.children[0], # (2 what if this was actually long body, - parameters.NOT_IMPLEMENTED_attr[-1], # )2 + parameters.children[-1], # )2 ] - parameters.NOT_IMPLEMENTED_attr = [ - parameters.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr[0], + parameters.children = [ + parameters.what_if_this_was_actually_long.children[0], body, - parameters.NOT_IMPLEMENTED_attr[-1], + parameters.children[-1], ] # type: ignore if ( NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments3_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments3_py.snap index 0c05857e26189..00e41d0c6a8dd 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments3_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments3_py.snap @@ -82,7 +82,7 @@ def func(): - if isinstance(exc_value, MultiError): + if NOT_IMPLEMENTED_call(): embedded = [] -- for exc in exc_value.exceptions: + for exc in exc_value.exceptions: - if exc not in _seen: - embedded.append( - # This should be left alone (before) @@ -97,7 +97,6 @@ def func(): - ) - # This should be left alone (after) - ) -+ for exc in exc_value.NOT_IMPLEMENTED_attr: + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + NOT_IMPLEMENTED_call() @@ -130,7 +129,7 @@ def func(): # Capture each of the exceptions in the MultiError along with each of their causes and contexts if NOT_IMPLEMENTED_call(): embedded = [] - for exc in exc_value.NOT_IMPLEMENTED_attr: + for exc in exc_value.exceptions: if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: NOT_IMPLEMENTED_call() diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments5_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments5_py.snap index debbe953785c2..ef6cfc7becd9b 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments5_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments5_py.snap @@ -88,9 +88,8 @@ if __name__ == "__main__": +++ Ruff @@ -1,6 +1,6 @@ while True: -- if something.changed: + if something.changed: - do.stuff() # trailing comment -+ if something.NOT_IMPLEMENTED_attr: + NOT_IMPLEMENTED_call() # trailing comment # Comment belongs to the `if` block. # This one belongs to the `while` block. @@ -118,11 +117,11 @@ if __name__ == "__main__": -try: - with open(some_other_file) as w: - w.write(data) -+NOT_YET_IMPLEMENTED_StmtTry - +- -except OSError: - print("problems") -- ++NOT_YET_IMPLEMENTED_StmtTry + -import sys +NOT_YET_IMPLEMENTED_StmtImport @@ -160,7 +159,7 @@ if __name__ == "__main__": ```py while True: - if something.NOT_IMPLEMENTED_attr: + if something.changed: NOT_IMPLEMENTED_call() # trailing comment # Comment belongs to the `if` block. # This one belongs to the `while` block. diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__empty_lines_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__empty_lines_py.snap index 099f07777cde0..e23d22d0e3b4a 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__empty_lines_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__empty_lines_py.snap @@ -105,7 +105,7 @@ def g(): ```diff --- Black +++ Ruff -@@ -1,89 +1,79 @@ +@@ -1,59 +1,46 @@ -"""Docstring.""" +"NOT_YET_IMPLEMENTED_STRING" @@ -119,12 +119,9 @@ def g(): + SPACE = "NOT_YET_IMPLEMENTED_STRING" + DOUBLESPACE = "NOT_YET_IMPLEMENTED_STRING" -- t = leaf.type -- p = leaf.parent # trailing comment -- v = leaf.value -+ t = leaf.NOT_IMPLEMENTED_attr -+ p = leaf.NOT_IMPLEMENTED_attr # trailing comment -+ v = leaf.NOT_IMPLEMENTED_attr + t = leaf.type + p = leaf.parent # trailing comment + v = leaf.value - if t in ALWAYS_NO_SPACE: + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: @@ -136,8 +133,7 @@ def g(): - assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}" + NOT_YET_IMPLEMENTED_StmtAssert -- prev = leaf.prev_sibling -+ prev = leaf.NOT_IMPLEMENTED_attr + prev = leaf.prev_sibling if not prev: - prevp = preceding_leaf(p) - if not prevp or prevp.type in OPENING_BRACKETS: @@ -154,10 +150,7 @@ def g(): - syms.argument, - }: + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: -+ if ( -+ prevp.NOT_IMPLEMENTED_attr -+ and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right -+ ): ++ if prevp.parent and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: return NO - elif prevp.type == token.DOUBLESTAR: @@ -169,10 +162,7 @@ def g(): - syms.dictsetmaker, - }: + elif NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: -+ if ( -+ prevp.NOT_IMPLEMENTED_attr -+ and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right -+ ): ++ if prevp.parent and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: return NO @@ -189,12 +179,9 @@ def g(): + SPACE = "NOT_YET_IMPLEMENTED_STRING" + DOUBLESPACE = "NOT_YET_IMPLEMENTED_STRING" -- t = leaf.type -- p = leaf.parent -- v = leaf.value -+ t = leaf.NOT_IMPLEMENTED_attr -+ p = leaf.NOT_IMPLEMENTED_attr -+ v = leaf.NOT_IMPLEMENTED_attr + t = leaf.type + p = leaf.parent +@@ -61,29 +48,23 @@ # Comment because comments @@ -209,8 +196,7 @@ def g(): - assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}" + NOT_YET_IMPLEMENTED_StmtAssert -- prev = leaf.prev_sibling -+ prev = leaf.NOT_IMPLEMENTED_attr + prev = leaf.prev_sibling if not prev: - prevp = preceding_leaf(p) + prevp = NOT_IMPLEMENTED_call() @@ -230,10 +216,7 @@ def g(): - syms.argument, - }: + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: -+ if ( -+ prevp.NOT_IMPLEMENTED_attr -+ and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right -+ ): ++ if prevp.parent and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: return NO ``` @@ -249,9 +232,9 @@ def f(): SPACE = "NOT_YET_IMPLEMENTED_STRING" DOUBLESPACE = "NOT_YET_IMPLEMENTED_STRING" - t = leaf.NOT_IMPLEMENTED_attr - p = leaf.NOT_IMPLEMENTED_attr # trailing comment - v = leaf.NOT_IMPLEMENTED_attr + t = leaf.type + p = leaf.parent # trailing comment + v = leaf.value if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: pass @@ -260,24 +243,18 @@ def f(): NOT_YET_IMPLEMENTED_StmtAssert - prev = leaf.NOT_IMPLEMENTED_attr + prev = leaf.prev_sibling if not prev: prevp = NOT_IMPLEMENTED_call() if not prevp or NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: return NO if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: - if ( - prevp.NOT_IMPLEMENTED_attr - and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right - ): + if prevp.parent and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: return NO elif NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: - if ( - prevp.NOT_IMPLEMENTED_attr - and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right - ): + if prevp.parent and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: return NO @@ -290,9 +267,9 @@ def g(): SPACE = "NOT_YET_IMPLEMENTED_STRING" DOUBLESPACE = "NOT_YET_IMPLEMENTED_STRING" - t = leaf.NOT_IMPLEMENTED_attr - p = leaf.NOT_IMPLEMENTED_attr - v = leaf.NOT_IMPLEMENTED_attr + t = leaf.type + p = leaf.parent + v = leaf.value # Comment because comments @@ -304,7 +281,7 @@ def g(): # Another comment because more comments NOT_YET_IMPLEMENTED_StmtAssert - prev = leaf.NOT_IMPLEMENTED_attr + prev = leaf.prev_sibling if not prev: prevp = NOT_IMPLEMENTED_call() @@ -314,10 +291,7 @@ def g(): return NO if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: - if ( - prevp.NOT_IMPLEMENTED_attr - and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right - ): + if prevp.parent and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: return NO ``` diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__expression_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__expression_py.snap index 78ff32e2ebc03..b2ff9dc82e405 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__expression_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__expression_py.snap @@ -276,7 +276,7 @@ last_call() Name None True -@@ -30,134 +31,120 @@ +@@ -30,98 +31,90 @@ -1 ~int and not v1 ^ 123 + v2 | True (~int) and (not ((v1 ^ (123 + v2)) | True)) @@ -297,8 +297,15 @@ last_call() -(str or None) if True else (str or bytes or None) -str or None if (1 if True else 2) else str or bytes or None -(str or None) if (1 if True else 2) else (str or bytes or None) +-( +- (super_long_variable_name or None) +- if (1 if super_long_test_name else 2) +- else (str or bytes or None) +-) +-{"2.7": dead, "3.7": (long_live or die_hard)} +-{"2.7": dead, "3.7": (long_live or die_hard), **{"3.6": verygood}} ++really ** -confusing ** ~operator**-precedence -+flags & ~select.NOT_IMPLEMENTED_attr and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right ++flags & ~select.EPOLLIN and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right +lambda x: True +lambda x: True +lambda x: True @@ -321,7 +328,9 @@ last_call() + "NOT_YET_IMPLEMENTED_STRING": (long_live or die_hard), + **{"NOT_YET_IMPLEMENTED_STRING": verygood}, +} -+{**a, **b, **c} + {**a, **b, **c} +-{"2.7", "3.6", "3.7", "3.8", "3.9", ("4.0" if gilectomy else "3.10")} +-({"a": "b"}, (True or False), (+value), "string", b"bytes") or None +{ + "NOT_YET_IMPLEMENTED_STRING", + "NOT_YET_IMPLEMENTED_STRING", @@ -330,16 +339,7 @@ last_call() + "NOT_YET_IMPLEMENTED_STRING", + (NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false), +} - ( -- (super_long_variable_name or None) -- if (1 if super_long_test_name else 2) -- else (str or bytes or None) --) --{"2.7": dead, "3.7": (long_live or die_hard)} --{"2.7": dead, "3.7": (long_live or die_hard), **{"3.6": verygood}} --{**a, **b, **c} --{"2.7", "3.6", "3.7", "3.8", "3.9", ("4.0" if gilectomy else "3.10")} --({"a": "b"}, (True or False), (+value), "string", b"bytes") or None ++( + {"NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING"}, + (True or False), + (+value), @@ -364,17 +364,17 @@ last_call() - 4, - 5, -] --[ -- 4, -- *a, -- 5, --] +[1, 2, 3] +[NOT_YET_IMPLEMENTED_ExprStarred] +[NOT_YET_IMPLEMENTED_ExprStarred] +[NOT_YET_IMPLEMENTED_ExprStarred, 4, 5] +[4, NOT_YET_IMPLEMENTED_ExprStarred, 5] [ +- 4, +- *a, +- 5, +-] +-[ this_is_a_very_long_variable_which_will_force_a_delimiter_split, element, another, @@ -415,11 +415,6 @@ last_call() -call(a, *gidgets[:2]) -call(**self.screen_kwargs) -call(b, **self.screen_kwargs) --lukasz.langa.pl --call.me(maybe) --(1).real --(1.0).real --....__class__ +NOT_YET_IMPLEMENTED_ExprSetComp +NOT_YET_IMPLEMENTED_ExprSetComp +NOT_YET_IMPLEMENTED_ExprSetComp @@ -445,13 +440,13 @@ last_call() +NOT_IMPLEMENTED_call() +NOT_IMPLEMENTED_call() +NOT_IMPLEMENTED_call() -+lukasz.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr + lukasz.langa.pl +-call.me(maybe) +NOT_IMPLEMENTED_call() -+1 .NOT_IMPLEMENTED_attr -+1.0 .NOT_IMPLEMENTED_attr -+....NOT_IMPLEMENTED_attr - list[str] - dict[str, int] + (1).real + (1.0).real + ....__class__ +@@ -130,34 +123,28 @@ tuple[str, ...] tuple[str, int, float, dict[str, int]] tuple[ @@ -504,12 +499,11 @@ last_call() numpy[-(c + 1) :, d] numpy[:, l[-2]] -numpy[:, ::-1] --numpy[np.newaxis, :] ++numpy[:, :: -1] + numpy[np.newaxis, :] -(str or None) if (sys.version_info[0] > (3,)) else (str or bytes or None) -{"2.7": dead, "3.7": long_live or die_hard} -{"2.7", "3.6", "3.7", "3.8", "3.9", "4.0" if gilectomy else "3.10"} -+numpy[:, :: -1] -+numpy[np.NOT_IMPLEMENTED_attr, :] +NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false +{ + "NOT_YET_IMPLEMENTED_STRING": dead, @@ -570,10 +564,7 @@ last_call() ) -what_is_up_with_those_new_coord_names = (coord_names | set(vars_to_create)) - set( - vars_to_remove -+what_is_up_with_those_new_coord_names = ( -+ (coord_names | NOT_IMPLEMENTED_call()) -+ - NOT_IMPLEMENTED_call() - ) +-) -result = ( - session.query(models.Customer.id) - .filter( @@ -591,7 +582,10 @@ last_call() - models.Customer.id.asc(), - ) - .all() --) ++what_is_up_with_those_new_coord_names = ( ++ (coord_names | NOT_IMPLEMENTED_call()) ++ - NOT_IMPLEMENTED_call() + ) -Ø = set() -authors.łukasz.say_thanks() +result = NOT_IMPLEMENTED_call() @@ -683,70 +677,40 @@ last_call() ): return True if ( -@@ -327,24 +296,44 @@ +@@ -327,13 +296,18 @@ ): return True if ( - ~aaaa.a + aaaa.b - aaaa.c * aaaa.d / aaaa.e -- | aaaa.f & aaaa.g % aaaa.h ^ aaaa.i << aaaa.k >> aaaa.l**aaaa.m // aaaa.n -+ ~aaaa.NOT_IMPLEMENTED_attr -+ + aaaa.NOT_IMPLEMENTED_attr -+ - aaaa.NOT_IMPLEMENTED_attr * aaaa.NOT_IMPLEMENTED_attr / aaaa.NOT_IMPLEMENTED_attr -+ | aaaa.NOT_IMPLEMENTED_attr -+ & aaaa.NOT_IMPLEMENTED_attr % aaaa.NOT_IMPLEMENTED_attr -+ ^ aaaa.NOT_IMPLEMENTED_attr -+ << aaaa.NOT_IMPLEMENTED_attr -+ >> aaaa.NOT_IMPLEMENTED_attr**aaaa.NOT_IMPLEMENTED_attr // aaaa.NOT_IMPLEMENTED_attr ++ ~aaaa.a ++ + aaaa.b ++ - aaaa.c * aaaa.d / aaaa.e + | aaaa.f & aaaa.g % aaaa.h ^ aaaa.i << aaaa.k >> aaaa.l**aaaa.m // aaaa.n ): return True if ( - ~aaaaaaaa.a + aaaaaaaa.b - aaaaaaaa.c @ aaaaaaaa.d / aaaaaaaa.e - | aaaaaaaa.f & aaaaaaaa.g % aaaaaaaa.h -- ^ aaaaaaaa.i << aaaaaaaa.k >> aaaaaaaa.l**aaaaaaaa.m // aaaaaaaa.n -+ ~aaaaaaaa.NOT_IMPLEMENTED_attr -+ + aaaaaaaa.NOT_IMPLEMENTED_attr -+ - aaaaaaaa.NOT_IMPLEMENTED_attr -+ @ aaaaaaaa.NOT_IMPLEMENTED_attr -+ / aaaaaaaa.NOT_IMPLEMENTED_attr -+ | aaaaaaaa.NOT_IMPLEMENTED_attr -+ & aaaaaaaa.NOT_IMPLEMENTED_attr % aaaaaaaa.NOT_IMPLEMENTED_attr -+ ^ aaaaaaaa.NOT_IMPLEMENTED_attr -+ << aaaaaaaa.NOT_IMPLEMENTED_attr -+ >> aaaaaaaa.NOT_IMPLEMENTED_attr -+ **aaaaaaaa.NOT_IMPLEMENTED_attr -+ // aaaaaaaa.NOT_IMPLEMENTED_attr ++ ~aaaaaaaa.a ++ + aaaaaaaa.b ++ - aaaaaaaa.c @ aaaaaaaa.d / aaaaaaaa.e ++ | aaaaaaaa.f ++ & aaaaaaaa.g % aaaaaaaa.h + ^ aaaaaaaa.i << aaaaaaaa.k >> aaaaaaaa.l**aaaaaaaa.m // aaaaaaaa.n ): return True - if ( -- ~aaaaaaaaaaaaaaaa.a -- + aaaaaaaaaaaaaaaa.b -- - aaaaaaaaaaaaaaaa.c * aaaaaaaaaaaaaaaa.d @ aaaaaaaaaaaaaaaa.e +@@ -341,7 +315,8 @@ + ~aaaaaaaaaaaaaaaa.a + + aaaaaaaaaaaaaaaa.b + - aaaaaaaaaaaaaaaa.c * aaaaaaaaaaaaaaaa.d @ aaaaaaaaaaaaaaaa.e - | aaaaaaaaaaaaaaaa.f & aaaaaaaaaaaaaaaa.g % aaaaaaaaaaaaaaaa.h -- ^ aaaaaaaaaaaaaaaa.i -- << aaaaaaaaaaaaaaaa.k -- >> aaaaaaaaaaaaaaaa.l**aaaaaaaaaaaaaaaa.m // aaaaaaaaaaaaaaaa.n -+ ~aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr -+ + aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr -+ - aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr -+ * aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr -+ @ aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr -+ | aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr -+ & aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr % aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr -+ ^ aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr -+ << aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr -+ >> aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr -+ **aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr -+ // aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr - ): - return True - ( -@@ -363,8 +352,9 @@ - bbbb >> bbbb * bbbb - ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -- ^ bbbb.a & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -+ ^ bbbb.NOT_IMPLEMENTED_attr -+ & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ++ | aaaaaaaaaaaaaaaa.f ++ & aaaaaaaaaaaaaaaa.g % aaaaaaaaaaaaaaaa.h + ^ aaaaaaaaaaaaaaaa.i + << aaaaaaaaaaaaaaaa.k + >> aaaaaaaaaaaaaaaa.l**aaaaaaaaaaaaaaaa.m // aaaaaaaaaaaaaaaa.n +@@ -366,5 +341,5 @@ + ^ bbbb.a & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ^ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ) -last_call() @@ -791,7 +755,7 @@ not great ~int and not v1 ^ 123 + v2 | True (~int) and (not ((v1 ^ (123 + v2)) | True)) +really ** -confusing ** ~operator**-precedence -flags & ~select.NOT_IMPLEMENTED_attr and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right +flags & ~select.EPOLLIN and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right lambda x: True lambda x: True lambda x: True @@ -872,11 +836,11 @@ NOT_IMPLEMENTED_call() NOT_IMPLEMENTED_call() NOT_IMPLEMENTED_call() NOT_IMPLEMENTED_call() -lukasz.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr +lukasz.langa.pl NOT_IMPLEMENTED_call() -1 .NOT_IMPLEMENTED_attr -1.0 .NOT_IMPLEMENTED_attr -....NOT_IMPLEMENTED_attr +(1).real +(1.0).real +....__class__ list[str] dict[str, int] tuple[str, ...] @@ -918,7 +882,7 @@ numpy[1 : c + 1, c] numpy[-(c + 1) :, d] numpy[:, l[-2]] numpy[:, :: -1] -numpy[np.NOT_IMPLEMENTED_attr, :] +numpy[np.newaxis, :] NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false { "NOT_YET_IMPLEMENTED_STRING": dead, @@ -1055,44 +1019,30 @@ if ( ): return True if ( - ~aaaa.NOT_IMPLEMENTED_attr - + aaaa.NOT_IMPLEMENTED_attr - - aaaa.NOT_IMPLEMENTED_attr * aaaa.NOT_IMPLEMENTED_attr / aaaa.NOT_IMPLEMENTED_attr - | aaaa.NOT_IMPLEMENTED_attr - & aaaa.NOT_IMPLEMENTED_attr % aaaa.NOT_IMPLEMENTED_attr - ^ aaaa.NOT_IMPLEMENTED_attr - << aaaa.NOT_IMPLEMENTED_attr - >> aaaa.NOT_IMPLEMENTED_attr**aaaa.NOT_IMPLEMENTED_attr // aaaa.NOT_IMPLEMENTED_attr + ~aaaa.a + + aaaa.b + - aaaa.c * aaaa.d / aaaa.e + | aaaa.f & aaaa.g % aaaa.h ^ aaaa.i << aaaa.k >> aaaa.l**aaaa.m // aaaa.n ): return True if ( - ~aaaaaaaa.NOT_IMPLEMENTED_attr - + aaaaaaaa.NOT_IMPLEMENTED_attr - - aaaaaaaa.NOT_IMPLEMENTED_attr - @ aaaaaaaa.NOT_IMPLEMENTED_attr - / aaaaaaaa.NOT_IMPLEMENTED_attr - | aaaaaaaa.NOT_IMPLEMENTED_attr - & aaaaaaaa.NOT_IMPLEMENTED_attr % aaaaaaaa.NOT_IMPLEMENTED_attr - ^ aaaaaaaa.NOT_IMPLEMENTED_attr - << aaaaaaaa.NOT_IMPLEMENTED_attr - >> aaaaaaaa.NOT_IMPLEMENTED_attr - **aaaaaaaa.NOT_IMPLEMENTED_attr - // aaaaaaaa.NOT_IMPLEMENTED_attr + ~aaaaaaaa.a + + aaaaaaaa.b + - aaaaaaaa.c @ aaaaaaaa.d / aaaaaaaa.e + | aaaaaaaa.f + & aaaaaaaa.g % aaaaaaaa.h + ^ aaaaaaaa.i << aaaaaaaa.k >> aaaaaaaa.l**aaaaaaaa.m // aaaaaaaa.n ): return True if ( - ~aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr - + aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr - - aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr - * aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr - @ aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr - | aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr - & aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr % aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr - ^ aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr - << aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr - >> aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr - **aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr - // aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr + ~aaaaaaaaaaaaaaaa.a + + aaaaaaaaaaaaaaaa.b + - aaaaaaaaaaaaaaaa.c * aaaaaaaaaaaaaaaa.d @ aaaaaaaaaaaaaaaa.e + | aaaaaaaaaaaaaaaa.f + & aaaaaaaaaaaaaaaa.g % aaaaaaaaaaaaaaaa.h + ^ aaaaaaaaaaaaaaaa.i + << aaaaaaaaaaaaaaaa.k + >> aaaaaaaaaaaaaaaa.l**aaaaaaaaaaaaaaaa.m // aaaaaaaaaaaaaaaa.n ): return True ( @@ -1111,8 +1061,7 @@ aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa bbbb >> bbbb * bbbb ( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - ^ bbbb.NOT_IMPLEMENTED_attr - & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + ^ bbbb.a & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ^ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ) NOT_IMPLEMENTED_call() diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff_py.snap index b99773a340f4c..de6064324a335 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff_py.snap @@ -253,19 +253,18 @@ d={'a':1, - async with some_connection() as conn: - await conn.do_what_i_mean('SELECT bobby, tables FROM xkcd', timeout=2) - await asyncio.sleep(1) --@asyncio.coroutine ++ "NOT_YET_IMPLEMENTED_STRING" ++ NOT_YET_IMPLEMENTED_StmtAsyncWith ++ await NOT_IMPLEMENTED_call() ++ ++ + @asyncio.coroutine -@some_decorator( -with_args=True, -many_args=[1,2,3] -) -def function_signature_stress_test(number:int,no_annotation=None,text:str='default',* ,debug:bool=False,**kwargs) -> str: - return text[number:-1] -+ "NOT_YET_IMPLEMENTED_STRING" -+ NOT_YET_IMPLEMENTED_StmtAsyncWith -+ await NOT_IMPLEMENTED_call() -+ -+ -+@asyncio.NOT_IMPLEMENTED_attr +@NOT_IMPLEMENTED_call() +def function_signature_stress_test( + number: int, @@ -399,7 +398,7 @@ d={'a':1, # fmt: off # hey, that won't work -@@ -130,13 +146,15 @@ +@@ -130,13 +146,13 @@ def on_and_off_broken(): @@ -414,13 +413,11 @@ d={'a':1, + this = NOT_IMPLEMENTED_call() + and_ = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right + NOT_IMPLEMENTED_call() -+ ( -+ now.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr -+ ) ++ now.considers.multiple.fmt.directives.within.one.prefix # fmt: on # fmt: off # ...but comments still get reformatted even though they should not be -@@ -145,80 +163,21 @@ +@@ -145,80 +161,21 @@ def long_lines(): if True: @@ -552,7 +549,7 @@ async def coroutine(arg, exec=False): await NOT_IMPLEMENTED_call() -@asyncio.NOT_IMPLEMENTED_attr +@asyncio.coroutine @NOT_IMPLEMENTED_call() def function_signature_stress_test( number: int, @@ -668,9 +665,7 @@ def on_and_off_broken(): this = NOT_IMPLEMENTED_call() and_ = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right NOT_IMPLEMENTED_call() - ( - now.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr - ) + now.considers.multiple.fmt.directives.within.one.prefix # fmt: on # fmt: off # ...but comments still get reformatted even though they should not be diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_py.snap index f983c55b44c22..9379157af1fb7 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_py.snap @@ -116,10 +116,10 @@ def __await__(): return (yield) +NOT_YET_IMPLEMENTED_StmtImport -from third_party import X, Y, Z +- +-from library import some_connection, some_decorator +NOT_YET_IMPLEMENTED_StmtImportFrom --from library import some_connection, some_decorator -- -f"trigger 3.6 mode" +NOT_YET_IMPLEMENTED_StmtImportFrom +NOT_YET_IMPLEMENTED_ExprJoinedStr @@ -154,9 +154,8 @@ def __await__(): return (yield) + await NOT_IMPLEMENTED_call() --@asyncio.coroutine + @asyncio.coroutine -@some_decorator(with_args=True, many_args=[1, 2, 3]) -+@asyncio.NOT_IMPLEMENTED_attr +@NOT_IMPLEMENTED_call() def function_signature_stress_test( number: int, @@ -323,7 +322,7 @@ async def coroutine(arg, exec=False): await NOT_IMPLEMENTED_call() -@asyncio.NOT_IMPLEMENTED_attr +@asyncio.coroutine @NOT_IMPLEMENTED_call() def function_signature_stress_test( number: int, diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__import_spacing_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__import_spacing_py.snap index 4160f7edaf384..df1dfc81f6322 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__import_spacing_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__import_spacing_py.snap @@ -62,7 +62,7 @@ __all__ = ( ```diff --- Black +++ Ruff -@@ -1,64 +1,42 @@ +@@ -1,54 +1,32 @@ -"""The asyncio package, tracking PEP 3156.""" +"NOT_YET_IMPLEMENTED_STRING" @@ -136,27 +136,7 @@ __all__ = ( +NOT_YET_IMPLEMENTED_StmtImportFrom __all__ = ( -- base_events.__all__ -- + coroutines.__all__ -- + events.__all__ -- + futures.__all__ -- + locks.__all__ -- + protocols.__all__ -- + runners.__all__ -- + queues.__all__ -- + streams.__all__ -- + tasks.__all__ -+ base_events.NOT_IMPLEMENTED_attr -+ + coroutines.NOT_IMPLEMENTED_attr -+ + events.NOT_IMPLEMENTED_attr -+ + futures.NOT_IMPLEMENTED_attr -+ + locks.NOT_IMPLEMENTED_attr -+ + protocols.NOT_IMPLEMENTED_attr -+ + runners.NOT_IMPLEMENTED_attr -+ + queues.NOT_IMPLEMENTED_attr -+ + streams.NOT_IMPLEMENTED_attr -+ + tasks.NOT_IMPLEMENTED_attr - ) + base_events.__all__ ``` ## Ruff Output @@ -193,16 +173,16 @@ NOT_YET_IMPLEMENTED_StmtImportFrom NOT_YET_IMPLEMENTED_StmtImportFrom __all__ = ( - base_events.NOT_IMPLEMENTED_attr - + coroutines.NOT_IMPLEMENTED_attr - + events.NOT_IMPLEMENTED_attr - + futures.NOT_IMPLEMENTED_attr - + locks.NOT_IMPLEMENTED_attr - + protocols.NOT_IMPLEMENTED_attr - + runners.NOT_IMPLEMENTED_attr - + queues.NOT_IMPLEMENTED_attr - + streams.NOT_IMPLEMENTED_attr - + tasks.NOT_IMPLEMENTED_attr + base_events.__all__ + + coroutines.__all__ + + events.__all__ + + futures.__all__ + + locks.__all__ + + protocols.__all__ + + runners.__all__ + + queues.__all__ + + streams.__all__ + + tasks.__all__ ) ``` diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__power_op_spacing_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__power_op_spacing_py.snap index 3ccecffed8c68..bf18bb0df84f5 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__power_op_spacing_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__power_op_spacing_py.snap @@ -86,19 +86,18 @@ return np.divide( -d = 5 ** f["hi"] -e = lazy(lambda **kwargs: 5) -f = f() ** 5 --g = a.b**c.d ++d = 5 ** f["NOT_YET_IMPLEMENTED_STRING"] ++e = NOT_IMPLEMENTED_call() ++f = NOT_IMPLEMENTED_call() ** 5 + g = a.b**c.d -h = 5 ** funcs.f() -i = funcs.f() ** 5 -j = super().name ** 5 -k = [(2**idx, value) for idx, value in pairs] -l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) -+d = 5 ** f["NOT_YET_IMPLEMENTED_STRING"] -+e = NOT_IMPLEMENTED_call() -+f = NOT_IMPLEMENTED_call() ** 5 -+g = a.NOT_IMPLEMENTED_attr**c.NOT_IMPLEMENTED_attr +h = 5 ** NOT_IMPLEMENTED_call() +i = NOT_IMPLEMENTED_call() ** 5 -+j = NOT_IMPLEMENTED_call().NOT_IMPLEMENTED_attr ** 5 ++j = NOT_IMPLEMENTED_call().name ** 5 +k = [i for i in []] +l = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right m = [([2**63], [1, 2**63])] @@ -119,19 +118,18 @@ return np.divide( -d = 5.0 ** f["hi"] -e = lazy(lambda **kwargs: 5) -f = f() ** 5.0 --g = a.b**c.d ++d = 5.0 ** f["NOT_YET_IMPLEMENTED_STRING"] ++e = NOT_IMPLEMENTED_call() ++f = NOT_IMPLEMENTED_call() ** 5.0 + g = a.b**c.d -h = 5.0 ** funcs.f() -i = funcs.f() ** 5.0 -j = super().name ** 5.0 -k = [(2.0**idx, value) for idx, value in pairs] -l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) -+d = 5.0 ** f["NOT_YET_IMPLEMENTED_STRING"] -+e = NOT_IMPLEMENTED_call() -+f = NOT_IMPLEMENTED_call() ** 5.0 -+g = a.NOT_IMPLEMENTED_attr**c.NOT_IMPLEMENTED_attr +h = 5.0 ** NOT_IMPLEMENTED_call() +i = NOT_IMPLEMENTED_call() ** 5.0 -+j = NOT_IMPLEMENTED_call().NOT_IMPLEMENTED_attr ** 5.0 ++j = NOT_IMPLEMENTED_call().name ** 5.0 +k = [i for i in []] +l = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right m = [([2.0**63.0], [1.0, 2**63.0])] @@ -184,10 +182,10 @@ c = -(5**2) d = 5 ** f["NOT_YET_IMPLEMENTED_STRING"] e = NOT_IMPLEMENTED_call() f = NOT_IMPLEMENTED_call() ** 5 -g = a.NOT_IMPLEMENTED_attr**c.NOT_IMPLEMENTED_attr +g = a.b**c.d h = 5 ** NOT_IMPLEMENTED_call() i = NOT_IMPLEMENTED_call() ** 5 -j = NOT_IMPLEMENTED_call().NOT_IMPLEMENTED_attr ** 5 +j = NOT_IMPLEMENTED_call().name ** 5 k = [i for i in []] l = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right m = [([2**63], [1, 2**63])] @@ -203,10 +201,10 @@ c = -(5.0**2.0) d = 5.0 ** f["NOT_YET_IMPLEMENTED_STRING"] e = NOT_IMPLEMENTED_call() f = NOT_IMPLEMENTED_call() ** 5.0 -g = a.NOT_IMPLEMENTED_attr**c.NOT_IMPLEMENTED_attr +g = a.b**c.d h = 5.0 ** NOT_IMPLEMENTED_call() i = NOT_IMPLEMENTED_call() ** 5.0 -j = NOT_IMPLEMENTED_call().NOT_IMPLEMENTED_attr ** 5.0 +j = NOT_IMPLEMENTED_call().name ** 5.0 k = [i for i in []] l = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right m = [([2.0**63.0], [1.0, 2**63.0])] diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__remove_for_brackets_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__remove_for_brackets_py.snap index d43018c8dcb74..b745fd054e283 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__remove_for_brackets_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__remove_for_brackets_py.snap @@ -44,7 +44,7 @@ for (((((k, v))))) in d.items(): - if hasattr(module, "_verify_python3_env"): - module._verify_python3_env = lambda: None + if NOT_IMPLEMENTED_call(): -+ module.NOT_IMPLEMENTED_attr = lambda x: True ++ module._verify_python3_env = lambda x: True # Brackets remain for long for loop lines for ( @@ -82,7 +82,7 @@ for k, v in NOT_IMPLEMENTED_call(): # Don't touch tuple brackets after `in` for module in (core, _unicodefun): if NOT_IMPLEMENTED_call(): - module.NOT_IMPLEMENTED_attr = lambda x: True + module._verify_python3_env = lambda x: True # Brackets remain for long for loop lines for ( diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__slices_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__slices_py.snap index 808ecffe6b8c6..f13a98ef7290d 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__slices_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__slices_py.snap @@ -76,11 +76,7 @@ x[ ```diff --- Black +++ Ruff -@@ -1,33 +1,33 @@ --slice[a.b : c.d] -+slice[a.NOT_IMPLEMENTED_attr : c.NOT_IMPLEMENTED_attr] - slice[d :: d + 1] - slice[d + 1 :: d] +@@ -4,30 +4,30 @@ slice[d::d] slice[0] slice[-1] @@ -144,7 +140,7 @@ x[ ## Ruff Output ```py -slice[a.NOT_IMPLEMENTED_attr : c.NOT_IMPLEMENTED_attr] +slice[a.b : c.d] slice[d :: d + 1] slice[d + 1 :: d] slice[d::d] diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__attribute_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__attribute_py.snap new file mode 100644 index 0000000000000..991210a185769 --- /dev/null +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__attribute_py.snap @@ -0,0 +1,73 @@ +--- +source: crates/ruff_python_formatter/src/lib.rs +expression: snapshot +--- +## Input +```py +( + a + # comment + .b # trailing comment +) + +( + a + # comment + .b # trailing dot comment # trailing identifier comment +) + +( + a + # comment + .b # trailing identifier comment +) + + +( + a + # comment + . # trailing dot comment + # in between + b # trailing identifier comment +) + + +aaaaaaaaaaaaaaaaaaaaa.lllllllllllllllllllllllllllloooooooooong.chaaaaaaaaaaaaaaaaaaaaaaiiiiiiiiiiiiiiiiiiiiiiinnnnnnnn.ooooooooooooooooooooooooofffffffff.aaaaaaaaaattr +``` + + + +## Output +```py +( + a + # comment + .b # trailing comment +) + +( + a + # comment + .b # trailing dot comment # trailing identifier comment +) + +( + a + # comment + .b # trailing identifier comment +) + + +( + a + # comment + . # trailing dot comment + # in between + b # trailing identifier comment +) + + +aaaaaaaaaaaaaaaaaaaaa.lllllllllllllllllllllllllllloooooooooong.chaaaaaaaaaaaaaaaaaaaaaaiiiiiiiiiiiiiiiiiiiiiiinnnnnnnn.ooooooooooooooooooooooooofffffffff.aaaaaaaaaattr +``` + + diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__boolean_operation_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__boolean_operation_py.snap index 4bc16ef83a501..cfc2bd43fe307 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__boolean_operation_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__boolean_operation_py.snap @@ -75,9 +75,9 @@ if ( ## Output ```py if ( - self.NOT_IMPLEMENTED_attr + self._proc # has the child process finished? - and self.NOT_IMPLEMENTED_attr + and self._returncode # the child process has finished, but the # transport hasn't been notified yet? and NOT_IMPLEMENTED_call() @@ -85,11 +85,11 @@ if ( pass if ( - self.NOT_IMPLEMENTED_attr - and self.NOT_IMPLEMENTED_attr + self._proc + and self._returncode and NOT_IMPLEMENTED_call() - and self.NOT_IMPLEMENTED_attr - and self.NOT_IMPLEMENTED_attr + and self._proc + and self._returncode and NOT_IMPLEMENTED_call() ): ... diff --git a/crates/ruff_python_formatter/src/trivia.rs b/crates/ruff_python_formatter/src/trivia.rs index 955f77c93f8df..942e75d3414b6 100644 --- a/crates/ruff_python_formatter/src/trivia.rs +++ b/crates/ruff_python_formatter/src/trivia.rs @@ -164,6 +164,9 @@ pub(crate) enum TokenKind { /// '*' Star, + /// `.`. + Dot, + /// Any other non trivia token. Always has a length of 1 Other, @@ -184,6 +187,7 @@ impl TokenKind { ':' => TokenKind::Colon, '/' => TokenKind::Slash, '*' => TokenKind::Star, + '.' => TokenKind::Dot, _ => TokenKind::Other, } }