mirror of
				https://github.com/astral-sh/ruff.git
				synced 2025-11-03 21:24:29 +00:00 
			
		
		
		
	Format Slice Expressions (#5047)
This formats slice expressions and subscript expressions. Spaces around the colons follows the same rules as black (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#slices): ```python e00 = "e"[:] e01 = "e"[:1] e02 = "e"[: a()] e10 = "e"[1:] e11 = "e"[1:1] e12 = "e"[1 : a()] e20 = "e"[a() :] e21 = "e"[a() : 1] e22 = "e"[a() : a()] e200 = "e"[a() : :] e201 = "e"[a() :: 1] e202 = "e"[a() :: a()] e210 = "e"[a() : 1 :] ``` Comment placement is different due to our very different infrastructure. If we have explicit bounds (e.g. `x[1:2]`) all comments get assigned as leading or trailing to the bound expression. If a bound is missing `[:]`, comments get marked as dangling and placed in the same section as they were originally in: ```python x = "x"[ # a # b : # c # d ] ``` to ```python x = "x"[ # a # b : # c # d ] ``` Except for the potential trailing end-of-line comments, all comments get formatted on their own line. This can be improved by keeping end-of-line comments after the opening bracket or after a colon as such but the changes were already complex enough. I added tests for comment placement and spaces.
This commit is contained in:
		
							parent
							
								
									4634560c80
								
							
						
					
					
						commit
						6155fd647d
					
				
					 22 changed files with 1065 additions and 430 deletions
				
			
		
							
								
								
									
										82
									
								
								crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/slice.py
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/slice.py
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,82 @@
 | 
				
			||||||
 | 
					# Handle comments both when lower and upper exist and when they don't
 | 
				
			||||||
 | 
					a1 = "a"[
 | 
				
			||||||
 | 
					    # a
 | 
				
			||||||
 | 
					    1  # b
 | 
				
			||||||
 | 
					    :  # c
 | 
				
			||||||
 | 
					    2  # d
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					a2 = "a"[
 | 
				
			||||||
 | 
					    # a
 | 
				
			||||||
 | 
					      # b
 | 
				
			||||||
 | 
					    :  # c
 | 
				
			||||||
 | 
					      # d
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check all places where comments can exist
 | 
				
			||||||
 | 
					b1 = "b"[ # a
 | 
				
			||||||
 | 
					    # b
 | 
				
			||||||
 | 
					    1 # c
 | 
				
			||||||
 | 
					    # d
 | 
				
			||||||
 | 
					    : # e
 | 
				
			||||||
 | 
					    # f
 | 
				
			||||||
 | 
					    2 # g
 | 
				
			||||||
 | 
					    # h
 | 
				
			||||||
 | 
					    : # i
 | 
				
			||||||
 | 
					    # j
 | 
				
			||||||
 | 
					    3 # k
 | 
				
			||||||
 | 
					    # l
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Handle the spacing from the colon correctly with upper leading comments
 | 
				
			||||||
 | 
					c1 = "c"[
 | 
				
			||||||
 | 
					    1
 | 
				
			||||||
 | 
					    :  # e
 | 
				
			||||||
 | 
					    # f
 | 
				
			||||||
 | 
					    2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					c2 = "c"[
 | 
				
			||||||
 | 
					    1
 | 
				
			||||||
 | 
					    :  # e
 | 
				
			||||||
 | 
					    2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					c3 = "c"[
 | 
				
			||||||
 | 
					    1
 | 
				
			||||||
 | 
					    :
 | 
				
			||||||
 | 
					    # f
 | 
				
			||||||
 | 
					    2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					c4 = "c"[
 | 
				
			||||||
 | 
					    1
 | 
				
			||||||
 | 
					    : # f
 | 
				
			||||||
 | 
					    2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# End of line comments
 | 
				
			||||||
 | 
					d1 = "d"[ # comment
 | 
				
			||||||
 | 
					    :
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					d2 = "d"[  # comment
 | 
				
			||||||
 | 
					    1:
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					d3 = "d"[
 | 
				
			||||||
 | 
					    1  # comment
 | 
				
			||||||
 | 
					    :
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Spacing around the colon(s)
 | 
				
			||||||
 | 
					def a():
 | 
				
			||||||
 | 
					    ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					e00 = "e"[:]
 | 
				
			||||||
 | 
					e01 = "e"[:1]
 | 
				
			||||||
 | 
					e02 = "e"[: a()]
 | 
				
			||||||
 | 
					e10 = "e"[1:]
 | 
				
			||||||
 | 
					e11 = "e"[1:1]
 | 
				
			||||||
 | 
					e12 = "e"[1 : a()]
 | 
				
			||||||
 | 
					e20 = "e"[a() :]
 | 
				
			||||||
 | 
					e21 = "e"[a() : 1]
 | 
				
			||||||
 | 
					e22 = "e"[a() : a()]
 | 
				
			||||||
 | 
					e200 = "e"[a() :: ]
 | 
				
			||||||
 | 
					e201 = "e"[a() :: 1]
 | 
				
			||||||
 | 
					e202 = "e"[a() :: a()]
 | 
				
			||||||
 | 
					e210 = "e"[a() : 1 :]
 | 
				
			||||||
| 
						 | 
					@ -1,16 +1,14 @@
 | 
				
			||||||
use std::cmp::Ordering;
 | 
					use crate::comments::visitor::{CommentPlacement, DecoratedComment};
 | 
				
			||||||
 | 
					use crate::comments::CommentLinePosition;
 | 
				
			||||||
use ruff_text_size::{TextRange, TextSize};
 | 
					use crate::expression::expr_slice::{assign_comment_in_slice, ExprSliceCommentSection};
 | 
				
			||||||
use rustpython_parser::ast::Ranged;
 | 
					use crate::trivia::{first_non_trivia_token_rev, SimpleTokenizer, Token, TokenKind};
 | 
				
			||||||
 | 
					use ruff_python_ast::node::{AnyNodeRef, AstNode};
 | 
				
			||||||
use ruff_python_ast::node::AnyNodeRef;
 | 
					 | 
				
			||||||
use ruff_python_ast::source_code::Locator;
 | 
					use ruff_python_ast::source_code::Locator;
 | 
				
			||||||
use ruff_python_ast::whitespace;
 | 
					use ruff_python_ast::whitespace;
 | 
				
			||||||
use ruff_python_whitespace::{PythonWhitespace, UniversalNewlines};
 | 
					use ruff_python_whitespace::{PythonWhitespace, UniversalNewlines};
 | 
				
			||||||
 | 
					use ruff_text_size::{TextRange, TextSize};
 | 
				
			||||||
use crate::comments::visitor::{CommentPlacement, DecoratedComment};
 | 
					use rustpython_parser::ast::{Expr, ExprSlice, Ranged};
 | 
				
			||||||
use crate::comments::CommentLinePosition;
 | 
					use std::cmp::Ordering;
 | 
				
			||||||
use crate::trivia::{SimpleTokenizer, Token, TokenKind};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Implements the custom comment placement logic.
 | 
					/// Implements the custom comment placement logic.
 | 
				
			||||||
pub(super) fn place_comment<'a>(
 | 
					pub(super) fn place_comment<'a>(
 | 
				
			||||||
| 
						 | 
					@ -30,6 +28,7 @@ pub(super) fn place_comment<'a>(
 | 
				
			||||||
        handle_trailing_binary_expression_left_or_operator_comment,
 | 
					        handle_trailing_binary_expression_left_or_operator_comment,
 | 
				
			||||||
        handle_leading_function_with_decorators_comment,
 | 
					        handle_leading_function_with_decorators_comment,
 | 
				
			||||||
        handle_dict_unpacking_comment,
 | 
					        handle_dict_unpacking_comment,
 | 
				
			||||||
 | 
					        handle_slice_comments,
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
    for handler in HANDLERS {
 | 
					    for handler in HANDLERS {
 | 
				
			||||||
        comment = match handler(comment, locator) {
 | 
					        comment = match handler(comment, locator) {
 | 
				
			||||||
| 
						 | 
					@ -837,6 +836,87 @@ fn handle_module_level_own_line_comment_before_class_or_function_comment<'a>(
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Handles the attaching comments left or right of the colon in a slice as trailing comment of the
 | 
				
			||||||
 | 
					/// preceding node or leading comment of the following node respectively.
 | 
				
			||||||
 | 
					/// ```python
 | 
				
			||||||
 | 
					/// a = "input"[
 | 
				
			||||||
 | 
					///     1 # c
 | 
				
			||||||
 | 
					///     # d
 | 
				
			||||||
 | 
					///     :2
 | 
				
			||||||
 | 
					/// ]
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					fn handle_slice_comments<'a>(
 | 
				
			||||||
 | 
					    comment: DecoratedComment<'a>,
 | 
				
			||||||
 | 
					    locator: &Locator,
 | 
				
			||||||
 | 
					) -> CommentPlacement<'a> {
 | 
				
			||||||
 | 
					    let expr_slice = match comment.enclosing_node() {
 | 
				
			||||||
 | 
					        AnyNodeRef::ExprSlice(expr_slice) => expr_slice,
 | 
				
			||||||
 | 
					        AnyNodeRef::ExprSubscript(expr_subscript) => {
 | 
				
			||||||
 | 
					            if expr_subscript.value.end() < expr_subscript.slice.start() {
 | 
				
			||||||
 | 
					                if let Expr::Slice(expr_slice) = expr_subscript.slice.as_ref() {
 | 
				
			||||||
 | 
					                    expr_slice
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    return CommentPlacement::Default(comment);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                return CommentPlacement::Default(comment);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        _ => return CommentPlacement::Default(comment),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let ExprSlice {
 | 
				
			||||||
 | 
					        range: _,
 | 
				
			||||||
 | 
					        lower,
 | 
				
			||||||
 | 
					        upper,
 | 
				
			||||||
 | 
					        step,
 | 
				
			||||||
 | 
					    } = expr_slice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Check for `foo[ # comment`, but only if they are on the same line
 | 
				
			||||||
 | 
					    let after_lbracket = matches!(
 | 
				
			||||||
 | 
					        first_non_trivia_token_rev(comment.slice().start(), locator.contents()),
 | 
				
			||||||
 | 
					        Some(Token {
 | 
				
			||||||
 | 
					            kind: TokenKind::LBracket,
 | 
				
			||||||
 | 
					            ..
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    if comment.line_position().is_end_of_line() && after_lbracket {
 | 
				
			||||||
 | 
					        // Keep comments after the opening bracket there by formatting them outside the
 | 
				
			||||||
 | 
					        // soft block indent
 | 
				
			||||||
 | 
					        // ```python
 | 
				
			||||||
 | 
					        // "a"[ # comment
 | 
				
			||||||
 | 
					        //     1:
 | 
				
			||||||
 | 
					        // ]
 | 
				
			||||||
 | 
					        // ```
 | 
				
			||||||
 | 
					        debug_assert!(
 | 
				
			||||||
 | 
					            matches!(comment.enclosing_node(), AnyNodeRef::ExprSubscript(_)),
 | 
				
			||||||
 | 
					            "{:?}",
 | 
				
			||||||
 | 
					            comment.enclosing_node()
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        return CommentPlacement::dangling(comment.enclosing_node(), comment);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let assignment =
 | 
				
			||||||
 | 
					        assign_comment_in_slice(comment.slice().range(), locator.contents(), expr_slice);
 | 
				
			||||||
 | 
					    let node = match assignment {
 | 
				
			||||||
 | 
					        ExprSliceCommentSection::Lower => lower,
 | 
				
			||||||
 | 
					        ExprSliceCommentSection::Upper => upper,
 | 
				
			||||||
 | 
					        ExprSliceCommentSection::Step => step,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if let Some(node) = node {
 | 
				
			||||||
 | 
					        if comment.slice().start() < node.start() {
 | 
				
			||||||
 | 
					            CommentPlacement::leading(node.as_ref().into(), comment)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // If a trailing comment is an end of line comment that's fine because we have a node
 | 
				
			||||||
 | 
					            // ahead of it
 | 
				
			||||||
 | 
					            CommentPlacement::trailing(node.as_ref().into(), comment)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        CommentPlacement::dangling(expr_slice.as_any_node_ref(), comment)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Finds the offset of the `/` that separates the positional only and arguments from the other arguments.
 | 
					/// Finds the offset of the `/` that separates the positional only and arguments from the other arguments.
 | 
				
			||||||
/// Returns `None` if the positional only separator `/` isn't present in the specified range.
 | 
					/// Returns `None` if the positional only separator `/` isn't present in the specified range.
 | 
				
			||||||
fn find_pos_only_slash_offset(
 | 
					fn find_pos_only_slash_offset(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,24 +1,262 @@
 | 
				
			||||||
 | 
					use crate::comments::{dangling_comments, Comments, SourceComment};
 | 
				
			||||||
use crate::expression::parentheses::{
 | 
					use crate::expression::parentheses::{
 | 
				
			||||||
    default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize,
 | 
					    default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use crate::{not_yet_implemented_custom_text, FormatNodeRule, PyFormatter};
 | 
					use crate::trivia::Token;
 | 
				
			||||||
 | 
					use crate::trivia::{first_non_trivia_token, TokenKind};
 | 
				
			||||||
use crate::comments::Comments;
 | 
					use crate::{AsFormat, FormatNodeRule, PyFormatter};
 | 
				
			||||||
use ruff_formatter::{write, Buffer, FormatResult};
 | 
					use ruff_formatter::prelude::{hard_line_break, line_suffix_boundary, space, text};
 | 
				
			||||||
 | 
					use ruff_formatter::{write, Buffer, Format, FormatError, FormatResult};
 | 
				
			||||||
 | 
					use ruff_python_ast::node::AstNode;
 | 
				
			||||||
 | 
					use ruff_python_ast::prelude::{Expr, Ranged};
 | 
				
			||||||
 | 
					use ruff_text_size::TextRange;
 | 
				
			||||||
use rustpython_parser::ast::ExprSlice;
 | 
					use rustpython_parser::ast::ExprSlice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Default)]
 | 
					#[derive(Default)]
 | 
				
			||||||
pub struct FormatExprSlice;
 | 
					pub struct FormatExprSlice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl FormatNodeRule<ExprSlice> for FormatExprSlice {
 | 
					impl FormatNodeRule<ExprSlice> for FormatExprSlice {
 | 
				
			||||||
    fn fmt_fields(&self, _item: &ExprSlice, f: &mut PyFormatter) -> FormatResult<()> {
 | 
					    /// This implementation deviates from black in that comments are attached to the section of the
 | 
				
			||||||
 | 
					    /// slice they originate in
 | 
				
			||||||
 | 
					    fn fmt_fields(&self, item: &ExprSlice, f: &mut PyFormatter) -> FormatResult<()> {
 | 
				
			||||||
 | 
					        // `[lower:upper:step]`
 | 
				
			||||||
 | 
					        let ExprSlice {
 | 
				
			||||||
 | 
					            range,
 | 
				
			||||||
 | 
					            lower,
 | 
				
			||||||
 | 
					            upper,
 | 
				
			||||||
 | 
					            step,
 | 
				
			||||||
 | 
					        } = item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let (first_colon, second_colon) =
 | 
				
			||||||
 | 
					            find_colons(f.context().contents(), *range, lower, upper)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Handle comment placement
 | 
				
			||||||
 | 
					        // In placements.rs, we marked comment for None nodes a dangling and associated all others
 | 
				
			||||||
 | 
					        // as leading or dangling wrt to a node. That means we either format a node and only have
 | 
				
			||||||
 | 
					        // to handle newlines and spacing, or the node is None and we insert the corresponding
 | 
				
			||||||
 | 
					        // slice of dangling comments
 | 
				
			||||||
 | 
					        let comments = f.context().comments().clone();
 | 
				
			||||||
 | 
					        let slice_dangling_comments = comments.dangling_comments(item.as_any_node_ref());
 | 
				
			||||||
 | 
					        // Put the dangling comments (where the nodes are missing) into buckets
 | 
				
			||||||
 | 
					        let first_colon_partition_index = slice_dangling_comments
 | 
				
			||||||
 | 
					            .partition_point(|x| x.slice().start() < first_colon.range.start());
 | 
				
			||||||
 | 
					        let (dangling_lower_comments, dangling_upper_step_comments) =
 | 
				
			||||||
 | 
					            slice_dangling_comments.split_at(first_colon_partition_index);
 | 
				
			||||||
 | 
					        let (dangling_upper_comments, dangling_step_comments) =
 | 
				
			||||||
 | 
					            if let Some(second_colon) = &second_colon {
 | 
				
			||||||
 | 
					                let second_colon_partition_index = dangling_upper_step_comments
 | 
				
			||||||
 | 
					                    .partition_point(|x| x.slice().start() < second_colon.range.start());
 | 
				
			||||||
 | 
					                dangling_upper_step_comments.split_at(second_colon_partition_index)
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                // Without a second colon they remaining dangling comments belong between the first
 | 
				
			||||||
 | 
					                // colon and the closing parentheses
 | 
				
			||||||
 | 
					                (dangling_upper_step_comments, [].as_slice())
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Ensure there a no dangling comments for a node if the node is present
 | 
				
			||||||
 | 
					        debug_assert!(lower.is_none() || dangling_lower_comments.is_empty());
 | 
				
			||||||
 | 
					        debug_assert!(upper.is_none() || dangling_upper_comments.is_empty());
 | 
				
			||||||
 | 
					        debug_assert!(step.is_none() || dangling_step_comments.is_empty());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Handle spacing around the colon(s)
 | 
				
			||||||
 | 
					        // https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#slices
 | 
				
			||||||
 | 
					        let lower_simple = lower.as_ref().map_or(true, |expr| is_simple_expr(expr));
 | 
				
			||||||
 | 
					        let upper_simple = upper.as_ref().map_or(true, |expr| is_simple_expr(expr));
 | 
				
			||||||
 | 
					        let step_simple = step.as_ref().map_or(true, |expr| is_simple_expr(expr));
 | 
				
			||||||
 | 
					        let all_simple = lower_simple && upper_simple && step_simple;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // lower
 | 
				
			||||||
 | 
					        if let Some(lower) = lower {
 | 
				
			||||||
 | 
					            write!(f, [lower.format(), line_suffix_boundary()])?;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            dangling_comments(dangling_lower_comments).fmt(f)?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // First colon
 | 
				
			||||||
 | 
					        // The spacing after the colon depends on both the lhs and the rhs:
 | 
				
			||||||
 | 
					        // ```
 | 
				
			||||||
 | 
					        // e00 = x[:]
 | 
				
			||||||
 | 
					        // e01 = x[:1]
 | 
				
			||||||
 | 
					        // e02 = x[: a()]
 | 
				
			||||||
 | 
					        // e10 = x[1:]
 | 
				
			||||||
 | 
					        // e11 = x[1:1]
 | 
				
			||||||
 | 
					        // e12 = x[1 : a()]
 | 
				
			||||||
 | 
					        // e20 = x[a() :]
 | 
				
			||||||
 | 
					        // e21 = x[a() : 1]
 | 
				
			||||||
 | 
					        // e22 = x[a() : a()]
 | 
				
			||||||
 | 
					        // e200 = "e"[a() : :]
 | 
				
			||||||
 | 
					        // e201 = "e"[a() :: 1]
 | 
				
			||||||
 | 
					        // e202 = "e"[a() :: a()]
 | 
				
			||||||
 | 
					        // ```
 | 
				
			||||||
 | 
					        if !all_simple {
 | 
				
			||||||
 | 
					            space().fmt(f)?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        text(":").fmt(f)?;
 | 
				
			||||||
 | 
					        // No upper node, no need for a space, e.g. `x[a() :]`
 | 
				
			||||||
 | 
					        if !all_simple && upper.is_some() {
 | 
				
			||||||
 | 
					            space().fmt(f)?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Upper
 | 
				
			||||||
 | 
					        if let Some(upper) = upper {
 | 
				
			||||||
 | 
					            let upper_leading_comments = comments.leading_comments(upper.as_ref());
 | 
				
			||||||
 | 
					            leading_comments_spacing(f, upper_leading_comments)?;
 | 
				
			||||||
 | 
					            write!(f, [upper.format(), line_suffix_boundary()])?;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if let Some(first) = dangling_upper_comments.first() {
 | 
				
			||||||
 | 
					                // Here the spacing for end-of-line comments works but own line comments need
 | 
				
			||||||
 | 
					                // explicit spacing
 | 
				
			||||||
 | 
					                if first.line_position().is_own_line() {
 | 
				
			||||||
 | 
					                    hard_line_break().fmt(f)?;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            dangling_comments(dangling_upper_comments).fmt(f)?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // (optionally) step
 | 
				
			||||||
 | 
					        if second_colon.is_some() {
 | 
				
			||||||
 | 
					            // Same spacing rules as for the first colon, except for the strange case when the
 | 
				
			||||||
 | 
					            // second colon exists, but neither upper nor step
 | 
				
			||||||
 | 
					            // ```
 | 
				
			||||||
 | 
					            // e200 = "e"[a() : :]
 | 
				
			||||||
 | 
					            // e201 = "e"[a() :: 1]
 | 
				
			||||||
 | 
					            // e202 = "e"[a() :: a()]
 | 
				
			||||||
 | 
					            // ```
 | 
				
			||||||
 | 
					            if !all_simple && (upper.is_some() || step.is_none()) {
 | 
				
			||||||
 | 
					                space().fmt(f)?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            text(":").fmt(f)?;
 | 
				
			||||||
 | 
					            // No step node, no need for a space
 | 
				
			||||||
 | 
					            if !all_simple && step.is_some() {
 | 
				
			||||||
 | 
					                space().fmt(f)?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if let Some(step) = step {
 | 
				
			||||||
 | 
					                let step_leading_comments = comments.leading_comments(step.as_ref());
 | 
				
			||||||
 | 
					                leading_comments_spacing(f, step_leading_comments)?;
 | 
				
			||||||
 | 
					                step.format().fmt(f)?;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                if !dangling_step_comments.is_empty() {
 | 
				
			||||||
 | 
					                    // Put the colon and comments on their own lines
 | 
				
			||||||
                    write!(
 | 
					                    write!(
 | 
				
			||||||
                        f,
 | 
					                        f,
 | 
				
			||||||
            [not_yet_implemented_custom_text(
 | 
					                        [hard_line_break(), dangling_comments(dangling_step_comments)]
 | 
				
			||||||
                "NOT_IMPLEMENTED_start:NOT_IMPLEMENTED_end"
 | 
					                    )?;
 | 
				
			||||||
            )]
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            debug_assert!(step.is_none(), "step can't exist without a second colon");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// We're in a slice, so we know there's a first colon, but with have to look into the source
 | 
				
			||||||
 | 
					/// to find out whether there is a second one, too, e.g. `[1:2]` and `[1:10:2]`.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Returns the first and optionally the second colon.
 | 
				
			||||||
 | 
					pub(crate) fn find_colons(
 | 
				
			||||||
 | 
					    contents: &str,
 | 
				
			||||||
 | 
					    range: TextRange,
 | 
				
			||||||
 | 
					    lower: &Option<Box<Expr>>,
 | 
				
			||||||
 | 
					    upper: &Option<Box<Expr>>,
 | 
				
			||||||
 | 
					) -> FormatResult<(Token, Option<Token>)> {
 | 
				
			||||||
 | 
					    let after_lower = lower
 | 
				
			||||||
 | 
					        .as_ref()
 | 
				
			||||||
 | 
					        .map_or(range.start(), |lower| lower.range().end());
 | 
				
			||||||
 | 
					    let first_colon =
 | 
				
			||||||
 | 
					        first_non_trivia_token(after_lower, contents).ok_or(FormatError::SyntaxError)?;
 | 
				
			||||||
 | 
					    if first_colon.kind != TokenKind::Colon {
 | 
				
			||||||
 | 
					        return Err(FormatError::SyntaxError);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let after_upper = upper
 | 
				
			||||||
 | 
					        .as_ref()
 | 
				
			||||||
 | 
					        .map_or(first_colon.end(), |upper| upper.range().end());
 | 
				
			||||||
 | 
					    // At least the closing bracket must exist, so there must be a token there
 | 
				
			||||||
 | 
					    let next_token =
 | 
				
			||||||
 | 
					        first_non_trivia_token(after_upper, contents).ok_or(FormatError::SyntaxError)?;
 | 
				
			||||||
 | 
					    let second_colon = if next_token.kind == TokenKind::Colon {
 | 
				
			||||||
 | 
					        debug_assert!(
 | 
				
			||||||
 | 
					            next_token.range.start() < range.end(),
 | 
				
			||||||
 | 
					            "The next token in a slice must either be a colon or the closing bracket"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        Some(next_token)
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    Ok((first_colon, second_colon))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Determines whether this expression needs a space around the colon
 | 
				
			||||||
 | 
					/// <https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#slices>
 | 
				
			||||||
 | 
					fn is_simple_expr(expr: &Expr) -> bool {
 | 
				
			||||||
 | 
					    matches!(expr, Expr::Constant(_) | Expr::Name(_))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub(crate) enum ExprSliceCommentSection {
 | 
				
			||||||
 | 
					    Lower,
 | 
				
			||||||
 | 
					    Upper,
 | 
				
			||||||
 | 
					    Step,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Assigns a comment to lower/upper/step in `[lower:upper:step]`.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// ```python
 | 
				
			||||||
 | 
					/// "sliceable"[
 | 
				
			||||||
 | 
					///     # lower comment
 | 
				
			||||||
 | 
					///     :
 | 
				
			||||||
 | 
					///     # upper comment
 | 
				
			||||||
 | 
					///     :
 | 
				
			||||||
 | 
					///     # step comment
 | 
				
			||||||
 | 
					/// ]
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					pub(crate) fn assign_comment_in_slice(
 | 
				
			||||||
 | 
					    comment: TextRange,
 | 
				
			||||||
 | 
					    contents: &str,
 | 
				
			||||||
 | 
					    expr_slice: &ExprSlice,
 | 
				
			||||||
 | 
					) -> ExprSliceCommentSection {
 | 
				
			||||||
 | 
					    let ExprSlice {
 | 
				
			||||||
 | 
					        range,
 | 
				
			||||||
 | 
					        lower,
 | 
				
			||||||
 | 
					        upper,
 | 
				
			||||||
 | 
					        step: _,
 | 
				
			||||||
 | 
					    } = expr_slice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let (first_colon, second_colon) = find_colons(contents, *range, lower, upper)
 | 
				
			||||||
 | 
					        .expect("SyntaxError when trying to parse slice");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if comment.start() < first_colon.range.start() {
 | 
				
			||||||
 | 
					        ExprSliceCommentSection::Lower
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        // We are to the right of the first colon
 | 
				
			||||||
 | 
					        if let Some(second_colon) = second_colon {
 | 
				
			||||||
 | 
					            if comment.start() < second_colon.range.start() {
 | 
				
			||||||
 | 
					                ExprSliceCommentSection::Upper
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                ExprSliceCommentSection::Step
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // No second colon means there is no step
 | 
				
			||||||
 | 
					            ExprSliceCommentSection::Upper
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Manual spacing for the leading comments of upper and step
 | 
				
			||||||
 | 
					fn leading_comments_spacing(
 | 
				
			||||||
 | 
					    f: &mut PyFormatter,
 | 
				
			||||||
 | 
					    leading_comments: &[SourceComment],
 | 
				
			||||||
 | 
					) -> FormatResult<()> {
 | 
				
			||||||
 | 
					    if let Some(first) = leading_comments.first() {
 | 
				
			||||||
 | 
					        if first.line_position().is_own_line() {
 | 
				
			||||||
 | 
					            // Insert a newline after the colon so the comment ends up on its own line
 | 
				
			||||||
 | 
					            hard_line_break().fmt(f)?;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // Insert the two spaces between the colon and the end-of-line comment after the colon
 | 
				
			||||||
 | 
					            write!(f, [space(), space()])?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl NeedsParentheses for ExprSlice {
 | 
					impl NeedsParentheses for ExprSlice {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,24 +1,52 @@
 | 
				
			||||||
 | 
					use crate::comments::{trailing_comments, Comments};
 | 
				
			||||||
use crate::expression::parentheses::{
 | 
					use crate::expression::parentheses::{
 | 
				
			||||||
    default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize,
 | 
					    default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use crate::{not_yet_implemented_custom_text, FormatNodeRule, PyFormatter};
 | 
					use crate::{AsFormat, FormatNodeRule, PyFormatter};
 | 
				
			||||||
 | 
					use ruff_formatter::prelude::{group, soft_block_indent, text};
 | 
				
			||||||
use crate::comments::Comments;
 | 
					use ruff_formatter::{format_args, write, Buffer, FormatResult};
 | 
				
			||||||
use ruff_formatter::{write, Buffer, FormatResult};
 | 
					use ruff_python_ast::node::AstNode;
 | 
				
			||||||
use rustpython_parser::ast::ExprSubscript;
 | 
					use rustpython_parser::ast::ExprSubscript;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Default)]
 | 
					#[derive(Default)]
 | 
				
			||||||
pub struct FormatExprSubscript;
 | 
					pub struct FormatExprSubscript;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl FormatNodeRule<ExprSubscript> for FormatExprSubscript {
 | 
					impl FormatNodeRule<ExprSubscript> for FormatExprSubscript {
 | 
				
			||||||
    fn fmt_fields(&self, _item: &ExprSubscript, f: &mut PyFormatter) -> FormatResult<()> {
 | 
					    fn fmt_fields(&self, item: &ExprSubscript, f: &mut PyFormatter) -> FormatResult<()> {
 | 
				
			||||||
 | 
					        let ExprSubscript {
 | 
				
			||||||
 | 
					            range: _,
 | 
				
			||||||
 | 
					            value,
 | 
				
			||||||
 | 
					            slice,
 | 
				
			||||||
 | 
					            ctx: _,
 | 
				
			||||||
 | 
					        } = item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let comments = f.context().comments().clone();
 | 
				
			||||||
 | 
					        let dangling_comments = comments.dangling_comments(item.as_any_node_ref());
 | 
				
			||||||
 | 
					        debug_assert!(
 | 
				
			||||||
 | 
					            dangling_comments.len() <= 1,
 | 
				
			||||||
 | 
					            "The subscript expression must have at most a single comment, the one after the bracket"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        write!(
 | 
					        write!(
 | 
				
			||||||
            f,
 | 
					            f,
 | 
				
			||||||
            [not_yet_implemented_custom_text(
 | 
					            [group(&format_args![
 | 
				
			||||||
                "NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]"
 | 
					                value.format(),
 | 
				
			||||||
            )]
 | 
					                text("["),
 | 
				
			||||||
 | 
					                trailing_comments(dangling_comments),
 | 
				
			||||||
 | 
					                soft_block_indent(&slice.format()),
 | 
				
			||||||
 | 
					                text("]")
 | 
				
			||||||
 | 
					            ])]
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn fmt_dangling_comments(
 | 
				
			||||||
 | 
					        &self,
 | 
				
			||||||
 | 
					        _node: &ExprSubscript,
 | 
				
			||||||
 | 
					        _f: &mut PyFormatter,
 | 
				
			||||||
 | 
					    ) -> FormatResult<()> {
 | 
				
			||||||
 | 
					        // Handled inside of `fmt_fields`
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl NeedsParentheses for ExprSubscript {
 | 
					impl NeedsParentheses for ExprSubscript {
 | 
				
			||||||
| 
						 | 
					@ -28,6 +56,9 @@ impl NeedsParentheses for ExprSubscript {
 | 
				
			||||||
        source: &str,
 | 
					        source: &str,
 | 
				
			||||||
        comments: &Comments,
 | 
					        comments: &Comments,
 | 
				
			||||||
    ) -> Parentheses {
 | 
					    ) -> 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,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,10 +2,10 @@ use crate::comments::{trailing_comments, Comments};
 | 
				
			||||||
use crate::expression::parentheses::{
 | 
					use crate::expression::parentheses::{
 | 
				
			||||||
    default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize,
 | 
					    default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use crate::prelude::*;
 | 
					 | 
				
			||||||
use crate::trivia::{SimpleTokenizer, TokenKind};
 | 
					use crate::trivia::{SimpleTokenizer, TokenKind};
 | 
				
			||||||
use crate::FormatNodeRule;
 | 
					use crate::{AsFormat, FormatNodeRule, PyFormatter};
 | 
				
			||||||
use ruff_formatter::FormatContext;
 | 
					use ruff_formatter::prelude::{hard_line_break, space, text};
 | 
				
			||||||
 | 
					use ruff_formatter::{Format, FormatContext, FormatResult};
 | 
				
			||||||
use ruff_python_ast::prelude::UnaryOp;
 | 
					use ruff_python_ast::prelude::UnaryOp;
 | 
				
			||||||
use ruff_text_size::{TextLen, TextRange};
 | 
					use ruff_text_size::{TextLen, TextRange};
 | 
				
			||||||
use rustpython_parser::ast::{ExprUnaryOp, Ranged};
 | 
					use rustpython_parser::ast::{ExprUnaryOp, Ranged};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -273,36 +273,7 @@ if True:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let formatted_code = printed.as_code();
 | 
					        let formatted_code = printed.as_code();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let reformatted = match format_module(formatted_code) {
 | 
					        ensure_stability_when_formatting_twice(formatted_code);
 | 
				
			||||||
            Ok(reformatted) => reformatted,
 | 
					 | 
				
			||||||
            Err(err) => {
 | 
					 | 
				
			||||||
                panic!(
 | 
					 | 
				
			||||||
                    "Expected formatted code to be valid syntax: {err}:\
 | 
					 | 
				
			||||||
                    \n---\n{formatted_code}---\n",
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if reformatted.as_code() != formatted_code {
 | 
					 | 
				
			||||||
            let diff = TextDiff::from_lines(formatted_code, reformatted.as_code())
 | 
					 | 
				
			||||||
                .unified_diff()
 | 
					 | 
				
			||||||
                .header("Formatted once", "Formatted twice")
 | 
					 | 
				
			||||||
                .to_string();
 | 
					 | 
				
			||||||
            panic!(
 | 
					 | 
				
			||||||
                r#"Reformatting the formatted code a second time resulted in formatting changes.
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
{diff}---
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Formatted once:
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
{formatted_code}---
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Formatted twice:
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
{}---"#,
 | 
					 | 
				
			||||||
                reformatted.as_code()
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if formatted_code == expected_output {
 | 
					        if formatted_code == expected_output {
 | 
				
			||||||
            // Black and Ruff formatting matches. Delete any existing snapshot files because the Black output
 | 
					            // Black and Ruff formatting matches. Delete any existing snapshot files because the Black output
 | 
				
			||||||
| 
						 | 
					@ -374,6 +345,8 @@ Formatted twice:
 | 
				
			||||||
        let reformatted =
 | 
					        let reformatted =
 | 
				
			||||||
            format_module(formatted_code).unwrap_or_else(|err| panic!("Expected formatted code to be valid syntax but it contains syntax errors: {err}\n{formatted_code}"));
 | 
					            format_module(formatted_code).unwrap_or_else(|err| panic!("Expected formatted code to be valid syntax but it contains syntax errors: {err}\n{formatted_code}"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ensure_stability_when_formatting_twice(formatted_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if reformatted.as_code() != formatted_code {
 | 
					        if reformatted.as_code() != formatted_code {
 | 
				
			||||||
            let diff = TextDiff::from_lines(formatted_code, reformatted.as_code())
 | 
					            let diff = TextDiff::from_lines(formatted_code, reformatted.as_code())
 | 
				
			||||||
                .unified_diff()
 | 
					                .unified_diff()
 | 
				
			||||||
| 
						 | 
					@ -406,6 +379,40 @@ Formatted twice:
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Format another time and make sure that there are no changes anymore
 | 
				
			||||||
 | 
					    fn ensure_stability_when_formatting_twice(formatted_code: &str) {
 | 
				
			||||||
 | 
					        let reformatted = match format_module(formatted_code) {
 | 
				
			||||||
 | 
					            Ok(reformatted) => reformatted,
 | 
				
			||||||
 | 
					            Err(err) => {
 | 
				
			||||||
 | 
					                panic!(
 | 
				
			||||||
 | 
					                    "Expected formatted code to be valid syntax: {err}:\
 | 
				
			||||||
 | 
					                    \n---\n{formatted_code}---\n",
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if reformatted.as_code() != formatted_code {
 | 
				
			||||||
 | 
					            let diff = TextDiff::from_lines(formatted_code, reformatted.as_code())
 | 
				
			||||||
 | 
					                .unified_diff()
 | 
				
			||||||
 | 
					                .header("Formatted once", "Formatted twice")
 | 
				
			||||||
 | 
					                .to_string();
 | 
				
			||||||
 | 
					            panic!(
 | 
				
			||||||
 | 
					                r#"Reformatting the formatted code a second time resulted in formatting changes.
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					{diff}---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Formatted once:
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					{formatted_code}---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Formatted twice:
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					{}---"#,
 | 
				
			||||||
 | 
					                reformatted.as_code()
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Use this test to debug the formatting of some snipped
 | 
					    /// Use this test to debug the formatting of some snipped
 | 
				
			||||||
    #[ignore]
 | 
					    #[ignore]
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,9 +73,8 @@ y = 100(no)
 | 
				
			||||||
+if 10 .NOT_IMPLEMENTED_attr:
 | 
					+if 10 .NOT_IMPLEMENTED_attr:
 | 
				
			||||||
     ...
 | 
					     ...
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
-y = 100[no]
 | 
					 y = 100[no]
 | 
				
			||||||
-y = 100(no)
 | 
					-y = 100(no)
 | 
				
			||||||
+y = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+y = NOT_IMPLEMENTED_call()
 | 
					+y = NOT_IMPLEMENTED_call()
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,7 +101,7 @@ x = -100.0000J
 | 
				
			||||||
if 10 .NOT_IMPLEMENTED_attr:
 | 
					if 10 .NOT_IMPLEMENTED_attr:
 | 
				
			||||||
    ...
 | 
					    ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
y = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					y = 100[no]
 | 
				
			||||||
y = NOT_IMPLEMENTED_call()
 | 
					y = NOT_IMPLEMENTED_call()
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -264,32 +264,30 @@ instruction()#comment with bad spacing
 | 
				
			||||||
     if typedargslist:
 | 
					     if typedargslist:
 | 
				
			||||||
-        parameters.children = [children[0], body, children[-1]]  # (1  # )1
 | 
					-        parameters.children = [children[0], body, children[-1]]  # (1  # )1
 | 
				
			||||||
-        parameters.children = [
 | 
					-        parameters.children = [
 | 
				
			||||||
-            children[0],
 | 
					 | 
				
			||||||
+        parameters.NOT_IMPLEMENTED_attr = [
 | 
					+        parameters.NOT_IMPLEMENTED_attr = [
 | 
				
			||||||
+            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],  # (1
 | 
					+            children[0],  # (1
 | 
				
			||||||
             body,
 | 
					+            body,
 | 
				
			||||||
-            children[-1],  # type: ignore
 | 
					+            children[-1],  # )1
 | 
				
			||||||
+            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],  # )1
 | 
					 | 
				
			||||||
+        ]
 | 
					+        ]
 | 
				
			||||||
+        parameters.NOT_IMPLEMENTED_attr = [
 | 
					+        parameters.NOT_IMPLEMENTED_attr = [
 | 
				
			||||||
+            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					             children[0],
 | 
				
			||||||
+            body,
 | 
					             body,
 | 
				
			||||||
+            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],  # type: ignore
 | 
					             children[-1],  # type: ignore
 | 
				
			||||||
         ]
 | 
					         ]
 | 
				
			||||||
     else:
 | 
					     else:
 | 
				
			||||||
-        parameters.children = [
 | 
					-        parameters.children = [
 | 
				
			||||||
-            parameters.children[0],  # (2 what if this was actually long
 | 
					-            parameters.children[0],  # (2 what if this was actually long
 | 
				
			||||||
+        parameters.NOT_IMPLEMENTED_attr = [
 | 
					+        parameters.NOT_IMPLEMENTED_attr = [
 | 
				
			||||||
+            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],  # (2 what if this was actually long
 | 
					+            parameters.NOT_IMPLEMENTED_attr[0],  # (2 what if this was actually long
 | 
				
			||||||
             body,
 | 
					             body,
 | 
				
			||||||
-            parameters.children[-1],  # )2
 | 
					-            parameters.children[-1],  # )2
 | 
				
			||||||
+            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],  # )2
 | 
					+            parameters.NOT_IMPLEMENTED_attr[-1],  # )2
 | 
				
			||||||
         ]
 | 
					         ]
 | 
				
			||||||
-        parameters.children = [parameters.what_if_this_was_actually_long.children[0], body, parameters.children[-1]]  # type: ignore
 | 
					-        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_value[NOT_IMPLEMENTED_key],
 | 
					+            parameters.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr[0],
 | 
				
			||||||
+            body,
 | 
					+            body,
 | 
				
			||||||
+            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					+            parameters.NOT_IMPLEMENTED_attr[-1],
 | 
				
			||||||
+        ]  # type: ignore
 | 
					+        ]  # type: ignore
 | 
				
			||||||
     if (
 | 
					     if (
 | 
				
			||||||
-        self._proc is not None
 | 
					-        self._proc is not None
 | 
				
			||||||
| 
						 | 
					@ -460,25 +458,25 @@ else:
 | 
				
			||||||
def inline_comments_in_brackets_ruin_everything():
 | 
					def inline_comments_in_brackets_ruin_everything():
 | 
				
			||||||
    if typedargslist:
 | 
					    if typedargslist:
 | 
				
			||||||
        parameters.NOT_IMPLEMENTED_attr = [
 | 
					        parameters.NOT_IMPLEMENTED_attr = [
 | 
				
			||||||
            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],  # (1
 | 
					            children[0],  # (1
 | 
				
			||||||
            body,
 | 
					            body,
 | 
				
			||||||
            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],  # )1
 | 
					            children[-1],  # )1
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
        parameters.NOT_IMPLEMENTED_attr = [
 | 
					        parameters.NOT_IMPLEMENTED_attr = [
 | 
				
			||||||
            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					            children[0],
 | 
				
			||||||
            body,
 | 
					            body,
 | 
				
			||||||
            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],  # type: ignore
 | 
					            children[-1],  # type: ignore
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        parameters.NOT_IMPLEMENTED_attr = [
 | 
					        parameters.NOT_IMPLEMENTED_attr = [
 | 
				
			||||||
            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],  # (2 what if this was actually long
 | 
					            parameters.NOT_IMPLEMENTED_attr[0],  # (2 what if this was actually long
 | 
				
			||||||
            body,
 | 
					            body,
 | 
				
			||||||
            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],  # )2
 | 
					            parameters.NOT_IMPLEMENTED_attr[-1],  # )2
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
        parameters.NOT_IMPLEMENTED_attr = [
 | 
					        parameters.NOT_IMPLEMENTED_attr = [
 | 
				
			||||||
            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					            parameters.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr[0],
 | 
				
			||||||
            body,
 | 
					            body,
 | 
				
			||||||
            NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					            parameters.NOT_IMPLEMENTED_attr[-1],
 | 
				
			||||||
        ]  # type: ignore
 | 
					        ]  # type: ignore
 | 
				
			||||||
    if (
 | 
					    if (
 | 
				
			||||||
        NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
 | 
					        NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -153,12 +153,9 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
     tup = (
 | 
					     tup = (
 | 
				
			||||||
         another_element,
 | 
					         another_element,
 | 
				
			||||||
@@ -84,35 +85,22 @@
 | 
					@@ -86,33 +87,20 @@
 | 
				
			||||||
 
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
 def func(
 | 
					 def func(
 | 
				
			||||||
-    a=some_list[0],  # type: int
 | 
					     a=some_list[0],  # type: int
 | 
				
			||||||
+    a=NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],  # type: int
 | 
					 | 
				
			||||||
 ):  # type: () -> int
 | 
					 ):  # type: () -> int
 | 
				
			||||||
-    c = call(
 | 
					-    c = call(
 | 
				
			||||||
-        0.0123,
 | 
					-        0.0123,
 | 
				
			||||||
| 
						 | 
					@ -293,7 +290,7 @@ def f(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def func(
 | 
					def func(
 | 
				
			||||||
    a=NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],  # type: int
 | 
					    a=some_list[0],  # type: int
 | 
				
			||||||
):  # type: () -> int
 | 
					):  # type: () -> int
 | 
				
			||||||
    c = NOT_IMPLEMENTED_call()
 | 
					    c = NOT_IMPLEMENTED_call()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -276,7 +276,7 @@ last_call()
 | 
				
			||||||
 Name
 | 
					 Name
 | 
				
			||||||
 None
 | 
					 None
 | 
				
			||||||
 True
 | 
					 True
 | 
				
			||||||
@@ -30,203 +31,178 @@
 | 
					@@ -30,134 +31,120 @@
 | 
				
			||||||
 -1
 | 
					 -1
 | 
				
			||||||
 ~int and not v1 ^ 123 + v2 | True
 | 
					 ~int and not v1 ^ 123 + v2 | True
 | 
				
			||||||
 (~int) and (not ((v1 ^ (123 + v2)) | True))
 | 
					 (~int) and (not ((v1 ^ (123 + v2)) | True))
 | 
				
			||||||
| 
						 | 
					@ -297,13 +297,6 @@ last_call()
 | 
				
			||||||
-(str or None) if True else (str or bytes or None)
 | 
					-(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
 | 
				
			||||||
-(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
 | 
					++really ** -confusing ** ~operator**-precedence
 | 
				
			||||||
+flags & ~select.NOT_IMPLEMENTED_attr and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
 | 
					+flags & ~select.NOT_IMPLEMENTED_attr and NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
 | 
				
			||||||
+lambda x: True
 | 
					+lambda x: True
 | 
				
			||||||
| 
						 | 
					@ -328,9 +321,7 @@ last_call()
 | 
				
			||||||
+    "NOT_YET_IMPLEMENTED_STRING": (long_live or die_hard),
 | 
					+    "NOT_YET_IMPLEMENTED_STRING": (long_live or die_hard),
 | 
				
			||||||
+    **{"NOT_YET_IMPLEMENTED_STRING": verygood},
 | 
					+    **{"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",
 | 
				
			||||||
+    "NOT_YET_IMPLEMENTED_STRING",
 | 
					+    "NOT_YET_IMPLEMENTED_STRING",
 | 
				
			||||||
| 
						 | 
					@ -339,7 +330,16 @@ last_call()
 | 
				
			||||||
+    "NOT_YET_IMPLEMENTED_STRING",
 | 
					+    "NOT_YET_IMPLEMENTED_STRING",
 | 
				
			||||||
+    (NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false),
 | 
					+    (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"},
 | 
					+    {"NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING"},
 | 
				
			||||||
+    (True or False),
 | 
					+    (True or False),
 | 
				
			||||||
+    (+value),
 | 
					+    (+value),
 | 
				
			||||||
| 
						 | 
					@ -352,7 +352,12 @@ last_call()
 | 
				
			||||||
 (1, 2, 3)
 | 
					 (1, 2, 3)
 | 
				
			||||||
 []
 | 
					 []
 | 
				
			||||||
 [1, 2, 3, 4, 5, 6, 7, 8, 9, (10 or A), (11 or B), (12 or C)]
 | 
					 [1, 2, 3, 4, 5, 6, 7, 8, 9, (10 or A), (11 or B), (12 or C)]
 | 
				
			||||||
-[
 | 
					+[1, 2, 3]
 | 
				
			||||||
 | 
					+[NOT_YET_IMPLEMENTED_ExprStarred]
 | 
				
			||||||
 | 
					+[NOT_YET_IMPLEMENTED_ExprStarred]
 | 
				
			||||||
 | 
					+[NOT_YET_IMPLEMENTED_ExprStarred, 4, 5]
 | 
				
			||||||
 | 
					+[4, NOT_YET_IMPLEMENTED_ExprStarred, 5]
 | 
				
			||||||
 | 
					 [
 | 
				
			||||||
-    1,
 | 
					-    1,
 | 
				
			||||||
-    2,
 | 
					-    2,
 | 
				
			||||||
-    3,
 | 
					-    3,
 | 
				
			||||||
| 
						 | 
					@ -369,12 +374,7 @@ last_call()
 | 
				
			||||||
-    *a,
 | 
					-    *a,
 | 
				
			||||||
-    5,
 | 
					-    5,
 | 
				
			||||||
-]
 | 
					-]
 | 
				
			||||||
+[1, 2, 3]
 | 
					-[
 | 
				
			||||||
+[NOT_YET_IMPLEMENTED_ExprStarred]
 | 
					 | 
				
			||||||
+[NOT_YET_IMPLEMENTED_ExprStarred]
 | 
					 | 
				
			||||||
+[NOT_YET_IMPLEMENTED_ExprStarred, 4, 5]
 | 
					 | 
				
			||||||
+[4, NOT_YET_IMPLEMENTED_ExprStarred, 5]
 | 
					 | 
				
			||||||
 [
 | 
					 | 
				
			||||||
     this_is_a_very_long_variable_which_will_force_a_delimiter_split,
 | 
					     this_is_a_very_long_variable_which_will_force_a_delimiter_split,
 | 
				
			||||||
     element,
 | 
					     element,
 | 
				
			||||||
     another,
 | 
					     another,
 | 
				
			||||||
| 
						 | 
					@ -393,6 +393,33 @@ last_call()
 | 
				
			||||||
-{i: j for i, j in ((1, "a"), (2, "b"), (3, "c"))}
 | 
					-{i: j for i, j in ((1, "a"), (2, "b"), (3, "c"))}
 | 
				
			||||||
-{a: b * 2 for a, b in dictionary.items()}
 | 
					-{a: b * 2 for a, b in dictionary.items()}
 | 
				
			||||||
-{a: b * -2 for a, b in dictionary.items()}
 | 
					-{a: b * -2 for a, b in dictionary.items()}
 | 
				
			||||||
 | 
					-{
 | 
				
			||||||
 | 
					-    k: v
 | 
				
			||||||
 | 
					-    for k, v in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
 | 
					-Python3 > Python2 > COBOL
 | 
				
			||||||
 | 
					-Life is Life
 | 
				
			||||||
 | 
					-call()
 | 
				
			||||||
 | 
					-call(arg)
 | 
				
			||||||
 | 
					-call(kwarg="hey")
 | 
				
			||||||
 | 
					-call(arg, kwarg="hey")
 | 
				
			||||||
 | 
					-call(arg, another, kwarg="hey", **kwargs)
 | 
				
			||||||
 | 
					-call(
 | 
				
			||||||
 | 
					-    this_is_a_very_long_variable_which_will_force_a_delimiter_split,
 | 
				
			||||||
 | 
					-    arg,
 | 
				
			||||||
 | 
					-    another,
 | 
				
			||||||
 | 
					-    kwarg="hey",
 | 
				
			||||||
 | 
					-    **kwargs,
 | 
				
			||||||
 | 
					-)  # note: no trailing comma pre-3.6
 | 
				
			||||||
 | 
					-call(*gidgets[:2])
 | 
				
			||||||
 | 
					-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
 | 
					+NOT_YET_IMPLEMENTED_ExprSetComp
 | 
				
			||||||
+NOT_YET_IMPLEMENTED_ExprSetComp
 | 
					+NOT_YET_IMPLEMENTED_ExprSetComp
 | 
				
			||||||
| 
						 | 
					@ -423,81 +450,22 @@ last_call()
 | 
				
			||||||
+1 .NOT_IMPLEMENTED_attr
 | 
					+1 .NOT_IMPLEMENTED_attr
 | 
				
			||||||
+1.0 .NOT_IMPLEMENTED_attr
 | 
					+1.0 .NOT_IMPLEMENTED_attr
 | 
				
			||||||
+....NOT_IMPLEMENTED_attr
 | 
					+....NOT_IMPLEMENTED_attr
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 list[str]
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 dict[str, int]
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 tuple[str, ...]
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 tuple[str, int, float, dict[str, int]]
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 tuple[
 | 
				
			||||||
+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					 | 
				
			||||||
+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					 | 
				
			||||||
+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					 | 
				
			||||||
+NOT_YET_IMPLEMENTED_StmtAnnAssign  # type: ignore
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
 | 
					 | 
				
			||||||
 {
 | 
					 | 
				
			||||||
-    k: v
 | 
					 | 
				
			||||||
-    for k, v in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension
 | 
					 | 
				
			||||||
+    "NOT_YET_IMPLEMENTED_STRING": dead,
 | 
					 | 
				
			||||||
+    "NOT_YET_IMPLEMENTED_STRING": long_live or die_hard,
 | 
					 | 
				
			||||||
 }
 | 
					 | 
				
			||||||
-Python3 > Python2 > COBOL
 | 
					 | 
				
			||||||
-Life is Life
 | 
					 | 
				
			||||||
-call()
 | 
					 | 
				
			||||||
-call(arg)
 | 
					 | 
				
			||||||
-call(kwarg="hey")
 | 
					 | 
				
			||||||
-call(arg, kwarg="hey")
 | 
					 | 
				
			||||||
-call(arg, another, kwarg="hey", **kwargs)
 | 
					 | 
				
			||||||
-call(
 | 
					 | 
				
			||||||
-    this_is_a_very_long_variable_which_will_force_a_delimiter_split,
 | 
					 | 
				
			||||||
-    arg,
 | 
					 | 
				
			||||||
-    another,
 | 
					 | 
				
			||||||
-    kwarg="hey",
 | 
					 | 
				
			||||||
-    **kwargs,
 | 
					 | 
				
			||||||
-)  # note: no trailing comma pre-3.6
 | 
					 | 
				
			||||||
-call(*gidgets[:2])
 | 
					 | 
				
			||||||
-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__
 | 
					 | 
				
			||||||
-list[str]
 | 
					 | 
				
			||||||
-dict[str, int]
 | 
					 | 
				
			||||||
-tuple[str, ...]
 | 
					 | 
				
			||||||
-tuple[str, int, float, dict[str, int]]
 | 
					 | 
				
			||||||
-tuple[
 | 
					 | 
				
			||||||
-    str,
 | 
					-    str,
 | 
				
			||||||
-    int,
 | 
					-    int,
 | 
				
			||||||
-    float,
 | 
					-    float,
 | 
				
			||||||
-    dict[str, int],
 | 
					-    dict[str, int],
 | 
				
			||||||
-]
 | 
					+    (
 | 
				
			||||||
 | 
					+        str,
 | 
				
			||||||
 | 
					+        int,
 | 
				
			||||||
 | 
					+        float,
 | 
				
			||||||
 | 
					+        dict[str, int],
 | 
				
			||||||
 | 
					+    )
 | 
				
			||||||
 | 
					 ]
 | 
				
			||||||
-very_long_variable_name_filters: t.List[
 | 
					-very_long_variable_name_filters: t.List[
 | 
				
			||||||
-    t.Tuple[str, t.Union[str, t.List[t.Optional[str]]]],
 | 
					-    t.Tuple[str, t.Union[str, t.List[t.Optional[str]]]],
 | 
				
			||||||
-]
 | 
					-]
 | 
				
			||||||
| 
						 | 
					@ -510,35 +478,43 @@ last_call()
 | 
				
			||||||
-xxxx_xxx_xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod(
 | 
					-xxxx_xxx_xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod(
 | 
				
			||||||
-    sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)
 | 
					-    sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)
 | 
				
			||||||
-)  # type: ignore
 | 
					-)  # type: ignore
 | 
				
			||||||
-slice[0]
 | 
					+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
-slice[0:1]
 | 
					+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
-slice[0:1:2]
 | 
					+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
-slice[:]
 | 
					+NOT_YET_IMPLEMENTED_StmtAnnAssign  # type: ignore
 | 
				
			||||||
 | 
					 slice[0]
 | 
				
			||||||
 | 
					 slice[0:1]
 | 
				
			||||||
 | 
					 slice[0:1:2]
 | 
				
			||||||
 | 
					 slice[:]
 | 
				
			||||||
-slice[:-1]
 | 
					-slice[:-1]
 | 
				
			||||||
-slice[1:]
 | 
					+slice[ : -1]
 | 
				
			||||||
 | 
					 slice[1:]
 | 
				
			||||||
-slice[::-1]
 | 
					-slice[::-1]
 | 
				
			||||||
-slice[d :: d + 1]
 | 
					+slice[ :: -1]
 | 
				
			||||||
-slice[:c, c - 1]
 | 
					 slice[d :: d + 1]
 | 
				
			||||||
-numpy[:, 0:1]
 | 
					 slice[:c, c - 1]
 | 
				
			||||||
 | 
					 numpy[:, 0:1]
 | 
				
			||||||
-numpy[:, :-1]
 | 
					-numpy[:, :-1]
 | 
				
			||||||
-numpy[0, :]
 | 
					+numpy[:,  : -1]
 | 
				
			||||||
-numpy[:, i]
 | 
					 numpy[0, :]
 | 
				
			||||||
-numpy[0, :2]
 | 
					 numpy[:, i]
 | 
				
			||||||
-numpy[:N, 0]
 | 
					 numpy[0, :2]
 | 
				
			||||||
-numpy[:2, :4]
 | 
					@@ -171,62 +158,58 @@
 | 
				
			||||||
-numpy[2:4, 1:5]
 | 
					 numpy[1 : c + 1, c]
 | 
				
			||||||
-numpy[4:, 2:]
 | 
					 numpy[-(c + 1) :, d]
 | 
				
			||||||
-numpy[:, (0, 1, 2, 5)]
 | 
					 numpy[:, l[-2]]
 | 
				
			||||||
-numpy[0, [0]]
 | 
					 | 
				
			||||||
-numpy[:, [i]]
 | 
					 | 
				
			||||||
-numpy[1 : c + 1, c]
 | 
					 | 
				
			||||||
-numpy[-(c + 1) :, d]
 | 
					 | 
				
			||||||
-numpy[:, l[-2]]
 | 
					 | 
				
			||||||
-numpy[:, ::-1]
 | 
					-numpy[:, ::-1]
 | 
				
			||||||
-numpy[np.newaxis, :]
 | 
					-numpy[np.newaxis, :]
 | 
				
			||||||
-(str or None) if (sys.version_info[0] > (3,)) else (str or bytes or None)
 | 
					-(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": 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"}
 | 
					-{"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,
 | 
				
			||||||
 | 
					+    "NOT_YET_IMPLEMENTED_STRING": long_live or die_hard,
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
+{
 | 
					+{
 | 
				
			||||||
+    "NOT_YET_IMPLEMENTED_STRING",
 | 
					+    "NOT_YET_IMPLEMENTED_STRING",
 | 
				
			||||||
+    "NOT_YET_IMPLEMENTED_STRING",
 | 
					+    "NOT_YET_IMPLEMENTED_STRING",
 | 
				
			||||||
| 
						 | 
					@ -585,7 +561,13 @@ last_call()
 | 
				
			||||||
-g = 1, *"ten"
 | 
					-g = 1, *"ten"
 | 
				
			||||||
-what_is_up_with_those_new_coord_names = (coord_names + set(vars_to_create)) + set(
 | 
					-what_is_up_with_those_new_coord_names = (coord_names + set(vars_to_create)) + set(
 | 
				
			||||||
-    vars_to_remove
 | 
					-    vars_to_remove
 | 
				
			||||||
-)
 | 
					+e = NOT_IMPLEMENTED_call()
 | 
				
			||||||
 | 
					+f = 1, NOT_YET_IMPLEMENTED_ExprStarred
 | 
				
			||||||
 | 
					+g = 1, NOT_YET_IMPLEMENTED_ExprStarred
 | 
				
			||||||
 | 
					+what_is_up_with_those_new_coord_names = (
 | 
				
			||||||
 | 
					+    (coord_names + NOT_IMPLEMENTED_call())
 | 
				
			||||||
 | 
					+    + NOT_IMPLEMENTED_call()
 | 
				
			||||||
 | 
					 )
 | 
				
			||||||
-what_is_up_with_those_new_coord_names = (coord_names | set(vars_to_create)) - set(
 | 
					-what_is_up_with_those_new_coord_names = (coord_names | set(vars_to_create)) - set(
 | 
				
			||||||
-    vars_to_remove
 | 
					-    vars_to_remove
 | 
				
			||||||
-)
 | 
					-)
 | 
				
			||||||
| 
						 | 
					@ -596,13 +578,7 @@ last_call()
 | 
				
			||||||
-    )
 | 
					-    )
 | 
				
			||||||
-    .order_by(models.Customer.id.asc())
 | 
					-    .order_by(models.Customer.id.asc())
 | 
				
			||||||
-    .all()
 | 
					-    .all()
 | 
				
			||||||
+e = NOT_IMPLEMENTED_call()
 | 
					-)
 | 
				
			||||||
+f = 1, NOT_YET_IMPLEMENTED_ExprStarred
 | 
					 | 
				
			||||||
+g = 1, NOT_YET_IMPLEMENTED_ExprStarred
 | 
					 | 
				
			||||||
+what_is_up_with_those_new_coord_names = (
 | 
					 | 
				
			||||||
+    (coord_names + NOT_IMPLEMENTED_call())
 | 
					 | 
				
			||||||
+    + NOT_IMPLEMENTED_call()
 | 
					 | 
				
			||||||
 )
 | 
					 | 
				
			||||||
-result = (
 | 
					-result = (
 | 
				
			||||||
-    session.query(models.Customer.id)
 | 
					-    session.query(models.Customer.id)
 | 
				
			||||||
-    .filter(
 | 
					-    .filter(
 | 
				
			||||||
| 
						 | 
					@ -625,7 +601,7 @@ last_call()
 | 
				
			||||||
 mapping = {
 | 
					 mapping = {
 | 
				
			||||||
     A: 0.25 * (10.0 / 12),
 | 
					     A: 0.25 * (10.0 / 12),
 | 
				
			||||||
     B: 0.1 * (10.0 / 12),
 | 
					     B: 0.1 * (10.0 / 12),
 | 
				
			||||||
@@ -236,64 +212,38 @@
 | 
					@@ -236,64 +219,38 @@
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 def gen():
 | 
					 def gen():
 | 
				
			||||||
| 
						 | 
					@ -714,7 +690,7 @@ last_call()
 | 
				
			||||||
 ):
 | 
					 ):
 | 
				
			||||||
     return True
 | 
					     return True
 | 
				
			||||||
 if (
 | 
					 if (
 | 
				
			||||||
@@ -327,24 +277,44 @@
 | 
					@@ -327,24 +284,44 @@
 | 
				
			||||||
 ):
 | 
					 ):
 | 
				
			||||||
     return True
 | 
					     return True
 | 
				
			||||||
 if (
 | 
					 if (
 | 
				
			||||||
| 
						 | 
					@ -771,7 +747,7 @@ last_call()
 | 
				
			||||||
 ):
 | 
					 ):
 | 
				
			||||||
     return True
 | 
					     return True
 | 
				
			||||||
 (
 | 
					 (
 | 
				
			||||||
@@ -363,8 +333,9 @@
 | 
					@@ -363,8 +340,9 @@
 | 
				
			||||||
 bbbb >> bbbb * bbbb
 | 
					 bbbb >> bbbb * bbbb
 | 
				
			||||||
 (
 | 
					 (
 | 
				
			||||||
     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 | 
					     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 | 
				
			||||||
| 
						 | 
					@ -908,41 +884,48 @@ NOT_IMPLEMENTED_call()
 | 
				
			||||||
1 .NOT_IMPLEMENTED_attr
 | 
					1 .NOT_IMPLEMENTED_attr
 | 
				
			||||||
1.0 .NOT_IMPLEMENTED_attr
 | 
					1.0 .NOT_IMPLEMENTED_attr
 | 
				
			||||||
....NOT_IMPLEMENTED_attr
 | 
					....NOT_IMPLEMENTED_attr
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					list[str]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					dict[str, int]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					tuple[str, ...]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					tuple[str, int, float, dict[str, int]]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					tuple[
 | 
				
			||||||
 | 
					    (
 | 
				
			||||||
 | 
					        str,
 | 
				
			||||||
 | 
					        int,
 | 
				
			||||||
 | 
					        float,
 | 
				
			||||||
 | 
					        dict[str, int],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
NOT_YET_IMPLEMENTED_StmtAnnAssign  # type: ignore
 | 
					NOT_YET_IMPLEMENTED_StmtAnnAssign  # type: ignore
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[0]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[0:1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[0:1:2]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[:]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[ : -1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[1:]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[ :: -1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[d :: d + 1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[:c, c - 1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[:, 0:1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[:,  : -1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[0, :]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[:, i]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[0, :2]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[:N, 0]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[:2, :4]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[2:4, 1:5]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[4:, 2:]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[:, (0, 1, 2, 5)]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[0, [0]]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[:, [i]]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[1 : c + 1, c]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[-(c + 1) :, d]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[:, l[-2]]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[:,  :: -1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					numpy[np.NOT_IMPLEMENTED_attr, :]
 | 
				
			||||||
NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
 | 
					NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    "NOT_YET_IMPLEMENTED_STRING": dead,
 | 
					    "NOT_YET_IMPLEMENTED_STRING": dead,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -273,7 +273,7 @@ d={'a':1,
 | 
				
			||||||
+    debug: bool = False,
 | 
					+    debug: bool = False,
 | 
				
			||||||
+    **kwargs,
 | 
					+    **kwargs,
 | 
				
			||||||
+) -> str:
 | 
					+) -> str:
 | 
				
			||||||
+    return NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+    return text[number : -1]
 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
 # fmt: on
 | 
					 # fmt: on
 | 
				
			||||||
| 
						 | 
					@ -296,7 +296,7 @@ d={'a':1,
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 def spaces_types(
 | 
					 def spaces_types(
 | 
				
			||||||
@@ -51,76 +70,61 @@
 | 
					@@ -51,76 +70,71 @@
 | 
				
			||||||
     d: dict = {},
 | 
					     d: dict = {},
 | 
				
			||||||
     e: bool = True,
 | 
					     e: bool = True,
 | 
				
			||||||
     f: int = -1,
 | 
					     f: int = -1,
 | 
				
			||||||
| 
						 | 
					@ -323,15 +323,22 @@ d={'a':1,
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 def subscriptlist():
 | 
					 def subscriptlist():
 | 
				
			||||||
-    atom[
 | 
					     atom[
 | 
				
			||||||
-        # fmt: off
 | 
					         # fmt: off
 | 
				
			||||||
-        'some big and',
 | 
					-        'some big and',
 | 
				
			||||||
-        'complex subscript',
 | 
					-        'complex subscript',
 | 
				
			||||||
-        # fmt: on
 | 
					-        # fmt: on
 | 
				
			||||||
-        goes + here,
 | 
					-        goes + here,
 | 
				
			||||||
-        andhere,
 | 
					-        andhere,
 | 
				
			||||||
-    ]
 | 
					+        (
 | 
				
			||||||
+    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+            "NOT_YET_IMPLEMENTED_STRING",
 | 
				
			||||||
 | 
					+            "NOT_YET_IMPLEMENTED_STRING",
 | 
				
			||||||
 | 
					+            # fmt: on
 | 
				
			||||||
 | 
					+            goes
 | 
				
			||||||
 | 
					+            + here,
 | 
				
			||||||
 | 
					+            andhere,
 | 
				
			||||||
 | 
					+        )
 | 
				
			||||||
 | 
					     ]
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 def import_as_names():
 | 
					 def import_as_names():
 | 
				
			||||||
| 
						 | 
					@ -390,7 +397,7 @@ d={'a':1,
 | 
				
			||||||
     # fmt: off
 | 
					     # fmt: off
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
     # hey, that won't work
 | 
					     # hey, that won't work
 | 
				
			||||||
@@ -130,13 +134,15 @@
 | 
					@@ -130,13 +144,15 @@
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 def on_and_off_broken():
 | 
					 def on_and_off_broken():
 | 
				
			||||||
| 
						 | 
					@ -411,7 +418,7 @@ d={'a':1,
 | 
				
			||||||
     # fmt: on
 | 
					     # fmt: on
 | 
				
			||||||
     # fmt: off
 | 
					     # fmt: off
 | 
				
			||||||
     # ...but comments still get reformatted even though they should not be
 | 
					     # ...but comments still get reformatted even though they should not be
 | 
				
			||||||
@@ -145,80 +151,21 @@
 | 
					@@ -145,80 +161,21 @@
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 def long_lines():
 | 
					 def long_lines():
 | 
				
			||||||
     if True:
 | 
					     if True:
 | 
				
			||||||
| 
						 | 
					@ -551,7 +558,7 @@ def function_signature_stress_test(
 | 
				
			||||||
    debug: bool = False,
 | 
					    debug: bool = False,
 | 
				
			||||||
    **kwargs,
 | 
					    **kwargs,
 | 
				
			||||||
) -> str:
 | 
					) -> str:
 | 
				
			||||||
    return NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					    return text[number : -1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# fmt: on
 | 
					# fmt: on
 | 
				
			||||||
| 
						 | 
					@ -595,7 +602,17 @@ something = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def subscriptlist():
 | 
					def subscriptlist():
 | 
				
			||||||
    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					    atom[
 | 
				
			||||||
 | 
					        # fmt: off
 | 
				
			||||||
 | 
					        (
 | 
				
			||||||
 | 
					            "NOT_YET_IMPLEMENTED_STRING",
 | 
				
			||||||
 | 
					            "NOT_YET_IMPLEMENTED_STRING",
 | 
				
			||||||
 | 
					            # fmt: on
 | 
				
			||||||
 | 
					            goes
 | 
				
			||||||
 | 
					            + here,
 | 
				
			||||||
 | 
					            andhere,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def import_as_names():
 | 
					def import_as_names():
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -167,7 +167,7 @@ def __await__(): return (yield)
 | 
				
			||||||
     **kwargs,
 | 
					     **kwargs,
 | 
				
			||||||
 ) -> str:
 | 
					 ) -> str:
 | 
				
			||||||
-    return text[number:-1]
 | 
					-    return text[number:-1]
 | 
				
			||||||
+    return NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+    return text[number : -1]
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
-def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r""):
 | 
					-def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r""):
 | 
				
			||||||
| 
						 | 
					@ -330,7 +330,7 @@ def function_signature_stress_test(
 | 
				
			||||||
    debug: bool = False,
 | 
					    debug: bool = False,
 | 
				
			||||||
    **kwargs,
 | 
					    **kwargs,
 | 
				
			||||||
) -> str:
 | 
					) -> str:
 | 
				
			||||||
    return NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					    return text[number : -1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def spaces(
 | 
					def spaces(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,7 +94,7 @@ some_module.some_function(
 | 
				
			||||||
     }
 | 
					     }
 | 
				
			||||||
     tup = (
 | 
					     tup = (
 | 
				
			||||||
         1,
 | 
					         1,
 | 
				
			||||||
@@ -24,45 +24,18 @@
 | 
					@@ -24,45 +24,23 @@
 | 
				
			||||||
 def f(
 | 
					 def f(
 | 
				
			||||||
     a: int = 1,
 | 
					     a: int = 1,
 | 
				
			||||||
 ):
 | 
					 ):
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,9 @@ some_module.some_function(
 | 
				
			||||||
-    call2(
 | 
					-    call2(
 | 
				
			||||||
-        arg=[1, 2, 3],
 | 
					-        arg=[1, 2, 3],
 | 
				
			||||||
-    )
 | 
					-    )
 | 
				
			||||||
-    x = {
 | 
					+    NOT_IMPLEMENTED_call()
 | 
				
			||||||
 | 
					+    NOT_IMPLEMENTED_call()
 | 
				
			||||||
 | 
					     x = {
 | 
				
			||||||
-        "a": 1,
 | 
					-        "a": 1,
 | 
				
			||||||
-        "b": 2,
 | 
					-        "b": 2,
 | 
				
			||||||
-    }["a"]
 | 
					-    }["a"]
 | 
				
			||||||
| 
						 | 
					@ -123,9 +125,11 @@ some_module.some_function(
 | 
				
			||||||
-            "h": 8,
 | 
					-            "h": 8,
 | 
				
			||||||
-        }["a"]
 | 
					-        }["a"]
 | 
				
			||||||
-    ):
 | 
					-    ):
 | 
				
			||||||
+    NOT_IMPLEMENTED_call()
 | 
					+        "NOT_YET_IMPLEMENTED_STRING": 1,
 | 
				
			||||||
+    NOT_IMPLEMENTED_call()
 | 
					+        "NOT_YET_IMPLEMENTED_STRING": 2,
 | 
				
			||||||
+    x = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+    }[
 | 
				
			||||||
 | 
					+        "NOT_YET_IMPLEMENTED_STRING"
 | 
				
			||||||
 | 
					+    ]
 | 
				
			||||||
+    if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right:
 | 
					+    if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right:
 | 
				
			||||||
         pass
 | 
					         pass
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
| 
						 | 
					@ -133,7 +137,7 @@ some_module.some_function(
 | 
				
			||||||
-def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
 | 
					-def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
 | 
				
			||||||
-    Set["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
 | 
					-    Set["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
 | 
				
			||||||
-):
 | 
					-):
 | 
				
			||||||
+def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]:
 | 
					+def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set["NOT_YET_IMPLEMENTED_STRING"]:
 | 
				
			||||||
     json = {
 | 
					     json = {
 | 
				
			||||||
-        "k": {
 | 
					-        "k": {
 | 
				
			||||||
-            "k2": {
 | 
					-            "k2": {
 | 
				
			||||||
| 
						 | 
					@ -148,7 +152,7 @@ some_module.some_function(
 | 
				
			||||||
     }
 | 
					     }
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
@@ -80,35 +53,16 @@
 | 
					@@ -80,35 +58,16 @@
 | 
				
			||||||
     pass
 | 
					     pass
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
| 
						 | 
					@ -221,12 +225,17 @@ def f(
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    NOT_IMPLEMENTED_call()
 | 
					    NOT_IMPLEMENTED_call()
 | 
				
			||||||
    NOT_IMPLEMENTED_call()
 | 
					    NOT_IMPLEMENTED_call()
 | 
				
			||||||
    x = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					    x = {
 | 
				
			||||||
 | 
					        "NOT_YET_IMPLEMENTED_STRING": 1,
 | 
				
			||||||
 | 
					        "NOT_YET_IMPLEMENTED_STRING": 2,
 | 
				
			||||||
 | 
					    }[
 | 
				
			||||||
 | 
					        "NOT_YET_IMPLEMENTED_STRING"
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
    if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right:
 | 
					    if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right:
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]:
 | 
					def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set["NOT_YET_IMPLEMENTED_STRING"]:
 | 
				
			||||||
    json = {
 | 
					    json = {
 | 
				
			||||||
        "NOT_YET_IMPLEMENTED_STRING": {
 | 
					        "NOT_YET_IMPLEMENTED_STRING": {
 | 
				
			||||||
            "NOT_YET_IMPLEMENTED_STRING": {"NOT_YET_IMPLEMENTED_STRING": [1]},
 | 
					            "NOT_YET_IMPLEMENTED_STRING": {"NOT_YET_IMPLEMENTED_STRING": [1]},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,25 +25,28 @@ list_of_types = [tuple[int,],]
 | 
				
			||||||
```diff
 | 
					```diff
 | 
				
			||||||
--- Black
 | 
					--- Black
 | 
				
			||||||
+++ Ruff
 | 
					+++ Ruff
 | 
				
			||||||
@@ -1,22 +1,12 @@
 | 
					@@ -1,22 +1,17 @@
 | 
				
			||||||
 # We should not treat the trailing comma
 | 
					 # We should not treat the trailing comma
 | 
				
			||||||
 # in a single-element subscript.
 | 
					 # in a single-element subscript.
 | 
				
			||||||
-a: tuple[int,]
 | 
					-a: tuple[int,]
 | 
				
			||||||
-b = tuple[int,]
 | 
					-b = tuple[int,]
 | 
				
			||||||
+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
+b = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+b = tuple[(int,)]
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 # The magic comma still applies to multi-element subscripts.
 | 
					 # The magic comma still applies to multi-element subscripts.
 | 
				
			||||||
-c: tuple[
 | 
					-c: tuple[
 | 
				
			||||||
-    int,
 | 
					-    int,
 | 
				
			||||||
-    int,
 | 
					-    int,
 | 
				
			||||||
-]
 | 
					-]
 | 
				
			||||||
-d = tuple[
 | 
					 | 
				
			||||||
-    int,
 | 
					 | 
				
			||||||
-    int,
 | 
					 | 
				
			||||||
-]
 | 
					 | 
				
			||||||
+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
+d = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 d = tuple[
 | 
				
			||||||
 | 
					-    int,
 | 
				
			||||||
 | 
					-    int,
 | 
				
			||||||
 | 
					+    (
 | 
				
			||||||
 | 
					+        int,
 | 
				
			||||||
 | 
					+        int,
 | 
				
			||||||
 | 
					+    )
 | 
				
			||||||
 | 
					 ]
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 # Magic commas still work as expected for non-subscripts.
 | 
					 # Magic commas still work as expected for non-subscripts.
 | 
				
			||||||
-small_list = [
 | 
					-small_list = [
 | 
				
			||||||
| 
						 | 
					@ -53,7 +56,7 @@ list_of_types = [tuple[int,],]
 | 
				
			||||||
-    tuple[int,],
 | 
					-    tuple[int,],
 | 
				
			||||||
-]
 | 
					-]
 | 
				
			||||||
+small_list = [1]
 | 
					+small_list = [1]
 | 
				
			||||||
+list_of_types = [NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]]
 | 
					+list_of_types = [tuple[(int,)]]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Ruff Output
 | 
					## Ruff Output
 | 
				
			||||||
| 
						 | 
					@ -62,15 +65,20 @@ list_of_types = [tuple[int,],]
 | 
				
			||||||
# We should not treat the trailing comma
 | 
					# We should not treat the trailing comma
 | 
				
			||||||
# in a single-element subscript.
 | 
					# in a single-element subscript.
 | 
				
			||||||
NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
b = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					b = tuple[(int,)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The magic comma still applies to multi-element subscripts.
 | 
					# The magic comma still applies to multi-element subscripts.
 | 
				
			||||||
NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
d = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					d = tuple[
 | 
				
			||||||
 | 
					    (
 | 
				
			||||||
 | 
					        int,
 | 
				
			||||||
 | 
					        int,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Magic commas still work as expected for non-subscripts.
 | 
					# Magic commas still work as expected for non-subscripts.
 | 
				
			||||||
small_list = [1]
 | 
					small_list = [1]
 | 
				
			||||||
list_of_types = [NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]]
 | 
					list_of_types = [tuple[(int,)]]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Black Output
 | 
					## Black Output
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,7 @@ return np.divide(
 | 
				
			||||||
-j = super().name ** 5
 | 
					-j = super().name ** 5
 | 
				
			||||||
-k = [(2**idx, value) for idx, value in pairs]
 | 
					-k = [(2**idx, value) for idx, value in pairs]
 | 
				
			||||||
-l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001)
 | 
					-l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001)
 | 
				
			||||||
+d = 5 ** NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+d = 5 ** f["NOT_YET_IMPLEMENTED_STRING"]
 | 
				
			||||||
+e = NOT_IMPLEMENTED_call()
 | 
					+e = NOT_IMPLEMENTED_call()
 | 
				
			||||||
+f = NOT_IMPLEMENTED_call() ** 5
 | 
					+f = NOT_IMPLEMENTED_call() ** 5
 | 
				
			||||||
+g = a.NOT_IMPLEMENTED_attr**c.NOT_IMPLEMENTED_attr
 | 
					+g = a.NOT_IMPLEMENTED_attr**c.NOT_IMPLEMENTED_attr
 | 
				
			||||||
| 
						 | 
					@ -125,7 +125,7 @@ return np.divide(
 | 
				
			||||||
-j = super().name ** 5.0
 | 
					-j = super().name ** 5.0
 | 
				
			||||||
-k = [(2.0**idx, value) for idx, value in pairs]
 | 
					-k = [(2.0**idx, value) for idx, value in pairs]
 | 
				
			||||||
-l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001)
 | 
					-l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001)
 | 
				
			||||||
+d = 5.0 ** NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+d = 5.0 ** f["NOT_YET_IMPLEMENTED_STRING"]
 | 
				
			||||||
+e = NOT_IMPLEMENTED_call()
 | 
					+e = NOT_IMPLEMENTED_call()
 | 
				
			||||||
+f = NOT_IMPLEMENTED_call() ** 5.0
 | 
					+f = NOT_IMPLEMENTED_call() ** 5.0
 | 
				
			||||||
+g = a.NOT_IMPLEMENTED_attr**c.NOT_IMPLEMENTED_attr
 | 
					+g = a.NOT_IMPLEMENTED_attr**c.NOT_IMPLEMENTED_attr
 | 
				
			||||||
| 
						 | 
					@ -181,7 +181,7 @@ def function_dont_replace_spaces():
 | 
				
			||||||
a = 5**~4
 | 
					a = 5**~4
 | 
				
			||||||
b = 5 ** NOT_IMPLEMENTED_call()
 | 
					b = 5 ** NOT_IMPLEMENTED_call()
 | 
				
			||||||
c = -(5**2)
 | 
					c = -(5**2)
 | 
				
			||||||
d = 5 ** NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					d = 5 ** f["NOT_YET_IMPLEMENTED_STRING"]
 | 
				
			||||||
e = NOT_IMPLEMENTED_call()
 | 
					e = NOT_IMPLEMENTED_call()
 | 
				
			||||||
f = NOT_IMPLEMENTED_call() ** 5
 | 
					f = NOT_IMPLEMENTED_call() ** 5
 | 
				
			||||||
g = a.NOT_IMPLEMENTED_attr**c.NOT_IMPLEMENTED_attr
 | 
					g = a.NOT_IMPLEMENTED_attr**c.NOT_IMPLEMENTED_attr
 | 
				
			||||||
| 
						 | 
					@ -200,7 +200,7 @@ r = x**y
 | 
				
			||||||
a = 5.0**~4.0
 | 
					a = 5.0**~4.0
 | 
				
			||||||
b = 5.0 ** NOT_IMPLEMENTED_call()
 | 
					b = 5.0 ** NOT_IMPLEMENTED_call()
 | 
				
			||||||
c = -(5.0**2.0)
 | 
					c = -(5.0**2.0)
 | 
				
			||||||
d = 5.0 ** NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					d = 5.0 ** f["NOT_YET_IMPLEMENTED_STRING"]
 | 
				
			||||||
e = NOT_IMPLEMENTED_call()
 | 
					e = NOT_IMPLEMENTED_call()
 | 
				
			||||||
f = NOT_IMPLEMENTED_call() ** 5.0
 | 
					f = NOT_IMPLEMENTED_call() ** 5.0
 | 
				
			||||||
g = a.NOT_IMPLEMENTED_attr**c.NOT_IMPLEMENTED_attr
 | 
					g = a.NOT_IMPLEMENTED_attr**c.NOT_IMPLEMENTED_attr
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,7 +40,7 @@ xxxxxxxxx_yyy_zzzzzzzz[xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxx
 | 
				
			||||||
-xxxxxxxxx_yyy_zzzzzzzz[
 | 
					-xxxxxxxxx_yyy_zzzzzzzz[
 | 
				
			||||||
-    xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxxx=1)
 | 
					-    xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxxx=1)
 | 
				
			||||||
-] = 1
 | 
					-] = 1
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key] = 1
 | 
					+xxxxxxxxx_yyy_zzzzzzzz[NOT_IMPLEMENTED_call(), NOT_IMPLEMENTED_call()] = 1
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Ruff Output
 | 
					## Ruff Output
 | 
				
			||||||
| 
						 | 
					@ -61,7 +61,7 @@ xxxxxxxxx_yyy_zzzzzzzz[xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Make when when the left side of assignment plus the opening paren "... = (" is
 | 
					# Make when when the left side of assignment plus the opening paren "... = (" is
 | 
				
			||||||
# exactly line length limit + 1, it won't be split like that.
 | 
					# exactly line length limit + 1, it won't be split like that.
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key] = 1
 | 
					xxxxxxxxx_yyy_zzzzzzzz[NOT_IMPLEMENTED_call(), NOT_IMPLEMENTED_call()] = 1
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Black Output
 | 
					## Black Output
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -123,35 +123,36 @@ def foo() -> tuple[int, int, int,]:
 | 
				
			||||||
     return 2
 | 
					     return 2
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
@@ -95,26 +99,14 @@
 | 
					@@ -99,22 +103,22 @@
 | 
				
			||||||
 
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
 # Return type with commas
 | 
					 | 
				
			||||||
-def foo() -> tuple[int, int, int]:
 | 
					 | 
				
			||||||
+def foo() -> NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]:
 | 
					 | 
				
			||||||
     return 2
 | 
					     return 2
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
-def foo() -> (
 | 
					-def foo() -> (
 | 
				
			||||||
-    tuple[
 | 
					-    tuple[
 | 
				
			||||||
-        loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
 | 
					+def foo() -> tuple[
 | 
				
			||||||
-        loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
 | 
					+    (
 | 
				
			||||||
-        loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
 | 
					         loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
 | 
				
			||||||
 | 
					         loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
 | 
				
			||||||
 | 
					         loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
 | 
				
			||||||
-    ]
 | 
					-    ]
 | 
				
			||||||
-):
 | 
					-):
 | 
				
			||||||
+def foo() -> NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]:
 | 
					+    )
 | 
				
			||||||
 | 
					+]:
 | 
				
			||||||
     return 2
 | 
					     return 2
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 # Magic trailing comma example
 | 
					 # Magic trailing comma example
 | 
				
			||||||
-def foo() -> (
 | 
					-def foo() -> (
 | 
				
			||||||
-    tuple[
 | 
					-    tuple[
 | 
				
			||||||
-        int,
 | 
					+def foo() -> tuple[
 | 
				
			||||||
-        int,
 | 
					+    (
 | 
				
			||||||
-        int,
 | 
					         int,
 | 
				
			||||||
 | 
					         int,
 | 
				
			||||||
 | 
					         int,
 | 
				
			||||||
-    ]
 | 
					-    ]
 | 
				
			||||||
-):
 | 
					-):
 | 
				
			||||||
+def foo() -> NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]:
 | 
					+    )
 | 
				
			||||||
 | 
					+]:
 | 
				
			||||||
     return 2
 | 
					     return 2
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -259,16 +260,28 @@ def foo() -> (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Return type with commas
 | 
					# Return type with commas
 | 
				
			||||||
def foo() -> NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]:
 | 
					def foo() -> tuple[int, int, int]:
 | 
				
			||||||
    return 2
 | 
					    return 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def foo() -> NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]:
 | 
					def foo() -> tuple[
 | 
				
			||||||
 | 
					    (
 | 
				
			||||||
 | 
					        loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
 | 
				
			||||||
 | 
					        loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
 | 
				
			||||||
 | 
					        loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					]:
 | 
				
			||||||
    return 2
 | 
					    return 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Magic trailing comma example
 | 
					# Magic trailing comma example
 | 
				
			||||||
def foo() -> NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]:
 | 
					def foo() -> tuple[
 | 
				
			||||||
 | 
					    (
 | 
				
			||||||
 | 
					        int,
 | 
				
			||||||
 | 
					        int,
 | 
				
			||||||
 | 
					        int,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					]:
 | 
				
			||||||
    return 2
 | 
					    return 2
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,26 +60,31 @@ func(
 | 
				
			||||||
```diff
 | 
					```diff
 | 
				
			||||||
--- Black
 | 
					--- Black
 | 
				
			||||||
+++ Ruff
 | 
					+++ Ruff
 | 
				
			||||||
@@ -1,25 +1,30 @@
 | 
					@@ -1,25 +1,35 @@
 | 
				
			||||||
 # We should not remove the trailing comma in a single-element subscript.
 | 
					 # We should not remove the trailing comma in a single-element subscript.
 | 
				
			||||||
-a: tuple[int,]
 | 
					-a: tuple[int,]
 | 
				
			||||||
-b = tuple[int,]
 | 
					-b = tuple[int,]
 | 
				
			||||||
+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
+b = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+b = tuple[(int,)]
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 # But commas in multiple element subscripts should be removed.
 | 
					 # But commas in multiple element subscripts should be removed.
 | 
				
			||||||
-c: tuple[int, int]
 | 
					-c: tuple[int, int]
 | 
				
			||||||
-d = tuple[int, int]
 | 
					-d = tuple[int, int]
 | 
				
			||||||
+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					+NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
+d = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+d = tuple[
 | 
				
			||||||
 | 
					+    (
 | 
				
			||||||
 | 
					+        int,
 | 
				
			||||||
 | 
					+        int,
 | 
				
			||||||
 | 
					+    )
 | 
				
			||||||
 | 
					+]
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 # Remove commas for non-subscripts.
 | 
					 # Remove commas for non-subscripts.
 | 
				
			||||||
 small_list = [1]
 | 
					 small_list = [1]
 | 
				
			||||||
-list_of_types = [tuple[int,]]
 | 
					-list_of_types = [tuple[int,]]
 | 
				
			||||||
+list_of_types = [NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]]
 | 
					+list_of_types = [tuple[(int,)]]
 | 
				
			||||||
 small_set = {1}
 | 
					 small_set = {1}
 | 
				
			||||||
-set_of_types = {tuple[int,]}
 | 
					-set_of_types = {tuple[int,]}
 | 
				
			||||||
+set_of_types = {NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]}
 | 
					+set_of_types = {tuple[(int,)]}
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 # Except single element tuples
 | 
					 # Except single element tuples
 | 
				
			||||||
 small_tuple = (1,)
 | 
					 small_tuple = (1,)
 | 
				
			||||||
| 
						 | 
					@ -108,17 +113,22 @@ func(
 | 
				
			||||||
```py
 | 
					```py
 | 
				
			||||||
# We should not remove the trailing comma in a single-element subscript.
 | 
					# We should not remove the trailing comma in a single-element subscript.
 | 
				
			||||||
NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
b = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					b = tuple[(int,)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# But commas in multiple element subscripts should be removed.
 | 
					# But commas in multiple element subscripts should be removed.
 | 
				
			||||||
NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
					NOT_YET_IMPLEMENTED_StmtAnnAssign
 | 
				
			||||||
d = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					d = tuple[
 | 
				
			||||||
 | 
					    (
 | 
				
			||||||
 | 
					        int,
 | 
				
			||||||
 | 
					        int,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Remove commas for non-subscripts.
 | 
					# Remove commas for non-subscripts.
 | 
				
			||||||
small_list = [1]
 | 
					small_list = [1]
 | 
				
			||||||
list_of_types = [NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]]
 | 
					list_of_types = [tuple[(int,)]]
 | 
				
			||||||
small_set = {1}
 | 
					small_set = {1}
 | 
				
			||||||
set_of_types = {NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]}
 | 
					set_of_types = {tuple[(int,)]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Except single element tuples
 | 
					# Except single element tuples
 | 
				
			||||||
small_tuple = (1,)
 | 
					small_tuple = (1,)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,158 +76,137 @@ x[
 | 
				
			||||||
```diff
 | 
					```diff
 | 
				
			||||||
--- Black
 | 
					--- Black
 | 
				
			||||||
+++ Ruff
 | 
					+++ Ruff
 | 
				
			||||||
@@ -1,59 +1,48 @@
 | 
					@@ -1,33 +1,33 @@
 | 
				
			||||||
-slice[a.b : c.d]
 | 
					-slice[a.b : c.d]
 | 
				
			||||||
-slice[d :: d + 1]
 | 
					+slice[a.NOT_IMPLEMENTED_attr : c.NOT_IMPLEMENTED_attr]
 | 
				
			||||||
-slice[d + 1 :: d]
 | 
					 slice[d :: d + 1]
 | 
				
			||||||
-slice[d::d]
 | 
					 slice[d + 1 :: d]
 | 
				
			||||||
-slice[0]
 | 
					 slice[d::d]
 | 
				
			||||||
-slice[-1]
 | 
					 slice[0]
 | 
				
			||||||
 | 
					 slice[-1]
 | 
				
			||||||
-slice[:-1]
 | 
					-slice[:-1]
 | 
				
			||||||
-slice[::-1]
 | 
					-slice[::-1]
 | 
				
			||||||
-slice[:c, c - 1]
 | 
					+slice[ : -1]
 | 
				
			||||||
-slice[c, c + 1, d::]
 | 
					+slice[ :: -1]
 | 
				
			||||||
-slice[ham[c::d] :: 1]
 | 
					 slice[:c, c - 1]
 | 
				
			||||||
-slice[ham[cheese**2 : -1] : 1 : 1, ham[1:2]]
 | 
					 slice[c, c + 1, d::]
 | 
				
			||||||
 | 
					 slice[ham[c::d] :: 1]
 | 
				
			||||||
 | 
					 slice[ham[cheese**2 : -1] : 1 : 1, ham[1:2]]
 | 
				
			||||||
-slice[:-1:]
 | 
					-slice[:-1:]
 | 
				
			||||||
-slice[lambda: None : lambda: None]
 | 
					-slice[lambda: None : lambda: None]
 | 
				
			||||||
-slice[lambda x, y, *args, really=2, **kwargs: None :, None::]
 | 
					-slice[lambda x, y, *args, really=2, **kwargs: None :, None::]
 | 
				
			||||||
-slice[1 or 2 : True and False]
 | 
					+slice[ : -1 :]
 | 
				
			||||||
 | 
					+slice[lambda x: True : lambda x: True]
 | 
				
			||||||
 | 
					+slice[lambda x: True :, None::]
 | 
				
			||||||
 | 
					 slice[1 or 2 : True and False]
 | 
				
			||||||
-slice[not so_simple : 1 < val <= 10]
 | 
					-slice[not so_simple : 1 < val <= 10]
 | 
				
			||||||
-slice[(1 for i in range(42)) : x]
 | 
					-slice[(1 for i in range(42)) : x]
 | 
				
			||||||
-slice[:: [i for i in range(42)]]
 | 
					-slice[:: [i for i in range(42)]]
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+slice[not so_simple : NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right]
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+slice[(i for i in []) : x]
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+slice[ :: [i for i in []]]
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 async def f():
 | 
					 async def f():
 | 
				
			||||||
-    slice[await x : [i async for i in arange(42)] : 42]
 | 
					-    slice[await x : [i async for i in arange(42)] : 42]
 | 
				
			||||||
+    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+    slice[await x : [i for i in []] : 42]
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 # These are from PEP-8:
 | 
					 # These are from PEP-8:
 | 
				
			||||||
-ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
 | 
					 ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
 | 
				
			||||||
-ham[lower:upper], ham[lower:upper:], ham[lower::step]
 | 
					 ham[lower:upper], ham[lower:upper:], ham[lower::step]
 | 
				
			||||||
+(
 | 
					 | 
				
			||||||
+    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
+    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
+    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
+    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
+    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
+)
 | 
					 | 
				
			||||||
+(
 | 
					 | 
				
			||||||
+    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
+    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
+    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
+)
 | 
					 | 
				
			||||||
 # ham[lower+offset : upper+offset]
 | 
					 # ham[lower+offset : upper+offset]
 | 
				
			||||||
-ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
 | 
					-ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
 | 
				
			||||||
-ham[lower + offset : upper + offset]
 | 
					+ham[ : NOT_IMPLEMENTED_call() : NOT_IMPLEMENTED_call()], ham[ :: NOT_IMPLEMENTED_call()]
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 ham[lower + offset : upper + offset]
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
-slice[::, ::]
 | 
					 slice[::, ::]
 | 
				
			||||||
-slice[
 | 
					@@ -50,10 +50,14 @@
 | 
				
			||||||
-    # A
 | 
					 slice[
 | 
				
			||||||
-    :
 | 
					     # A
 | 
				
			||||||
-    # B
 | 
					     1
 | 
				
			||||||
-    :
 | 
					 | 
				
			||||||
-    # C
 | 
					 | 
				
			||||||
-]
 | 
					 | 
				
			||||||
-slice[
 | 
					 | 
				
			||||||
-    # A
 | 
					 | 
				
			||||||
-    1:
 | 
					 | 
				
			||||||
-    # B
 | 
					 | 
				
			||||||
-    2:
 | 
					 | 
				
			||||||
-    # C
 | 
					 | 
				
			||||||
-    3
 | 
					 | 
				
			||||||
-]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
-slice[
 | 
					 | 
				
			||||||
-    # A
 | 
					 | 
				
			||||||
-    1
 | 
					 | 
				
			||||||
-    + 2 :
 | 
					-    + 2 :
 | 
				
			||||||
-    # B
 | 
					+    + 2 : 
 | 
				
			||||||
 | 
					     # B
 | 
				
			||||||
-    3 :
 | 
					-    3 :
 | 
				
			||||||
-    # C
 | 
					+    3 : 
 | 
				
			||||||
-    4
 | 
					     # C
 | 
				
			||||||
-]
 | 
					     4
 | 
				
			||||||
 | 
					 ]
 | 
				
			||||||
-x[1:2:3]  # A  # B  # C
 | 
					-x[1:2:3]  # A  # B  # C
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+x[
 | 
				
			||||||
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+    1:  # A
 | 
				
			||||||
 | 
					+    2:  # B
 | 
				
			||||||
 | 
					+    3  # C
 | 
				
			||||||
 | 
					+]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Ruff Output
 | 
					## Ruff Output
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```py
 | 
					```py
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[a.NOT_IMPLEMENTED_attr : c.NOT_IMPLEMENTED_attr]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[d :: d + 1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[d + 1 :: d]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[d::d]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[0]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[-1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[ : -1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[ :: -1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[:c, c - 1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[c, c + 1, d::]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[ham[c::d] :: 1]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[ham[cheese**2 : -1] : 1 : 1, ham[1:2]]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[ : -1 :]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[lambda x: True : lambda x: True]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[lambda x: True :, None::]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[1 or 2 : True and False]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[not so_simple : NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[(i for i in []) : x]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[ :: [i for i in []]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async def f():
 | 
					async def f():
 | 
				
			||||||
    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					    slice[await x : [i for i in []] : 42]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# These are from PEP-8:
 | 
					# These are from PEP-8:
 | 
				
			||||||
(
 | 
					ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
 | 
				
			||||||
    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					ham[lower:upper], ham[lower:upper:], ham[lower::step]
 | 
				
			||||||
    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
(
 | 
					 | 
				
			||||||
    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
    NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
# ham[lower+offset : upper+offset]
 | 
					# ham[lower+offset : upper+offset]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					ham[ : NOT_IMPLEMENTED_call() : NOT_IMPLEMENTED_call()], ham[ :: NOT_IMPLEMENTED_call()]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					ham[lower + offset : upper + offset]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[::, ::]
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					    # A
 | 
				
			||||||
 | 
					    :
 | 
				
			||||||
 | 
					    # B
 | 
				
			||||||
 | 
					    :
 | 
				
			||||||
 | 
					    # C
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					slice[
 | 
				
			||||||
 | 
					    # A
 | 
				
			||||||
 | 
					    1:
 | 
				
			||||||
 | 
					    # B
 | 
				
			||||||
 | 
					    2:
 | 
				
			||||||
 | 
					    # C
 | 
				
			||||||
 | 
					    3
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					slice[
 | 
				
			||||||
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					    # A
 | 
				
			||||||
 | 
					    1
 | 
				
			||||||
 | 
					    + 2 : 
 | 
				
			||||||
 | 
					    # B
 | 
				
			||||||
 | 
					    3 : 
 | 
				
			||||||
 | 
					    # C
 | 
				
			||||||
 | 
					    4
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					x[
 | 
				
			||||||
 | 
					    1:  # A
 | 
				
			||||||
 | 
					    2:  # B
 | 
				
			||||||
 | 
					    3  # C
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Black Output
 | 
					## Black Output
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(
 | 
				
			||||||
```diff
 | 
					```diff
 | 
				
			||||||
--- Black
 | 
					--- Black
 | 
				
			||||||
+++ Ruff
 | 
					+++ Ruff
 | 
				
			||||||
@@ -1,50 +1,26 @@
 | 
					@@ -1,50 +1,30 @@
 | 
				
			||||||
-zero(
 | 
					-zero(
 | 
				
			||||||
-    one,
 | 
					-    one,
 | 
				
			||||||
-).two(
 | 
					-).two(
 | 
				
			||||||
| 
						 | 
					@ -86,7 +86,11 @@ assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(
 | 
				
			||||||
-        },
 | 
					-        },
 | 
				
			||||||
-        api_key=api_key,
 | 
					-        api_key=api_key,
 | 
				
			||||||
-    )["extensions"]["sdk"]["token"]
 | 
					-    )["extensions"]["sdk"]["token"]
 | 
				
			||||||
+    return NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					+    return NOT_IMPLEMENTED_call()["NOT_YET_IMPLEMENTED_STRING"][
 | 
				
			||||||
 | 
					+        "NOT_YET_IMPLEMENTED_STRING"
 | 
				
			||||||
 | 
					+    ][
 | 
				
			||||||
 | 
					+        "NOT_YET_IMPLEMENTED_STRING"
 | 
				
			||||||
 | 
					+    ]
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 # Edge case where a bug in a working-in-progress version of
 | 
					 # Edge case where a bug in a working-in-progress version of
 | 
				
			||||||
| 
						 | 
					@ -126,7 +130,11 @@ NOT_IMPLEMENTED_call()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Example from https://github.com/psf/black/issues/3229
 | 
					# Example from https://github.com/psf/black/issues/3229
 | 
				
			||||||
def refresh_token(self, device_family, refresh_token, api_key):
 | 
					def refresh_token(self, device_family, refresh_token, api_key):
 | 
				
			||||||
    return NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
 | 
					    return NOT_IMPLEMENTED_call()["NOT_YET_IMPLEMENTED_STRING"][
 | 
				
			||||||
 | 
					        "NOT_YET_IMPLEMENTED_STRING"
 | 
				
			||||||
 | 
					    ][
 | 
				
			||||||
 | 
					        "NOT_YET_IMPLEMENTED_STRING"
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Edge case where a bug in a working-in-progress version of
 | 
					# Edge case where a bug in a working-in-progress version of
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,177 @@
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					source: crates/ruff_python_formatter/src/lib.rs
 | 
				
			||||||
 | 
					expression: snapshot
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					## Input
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					# Handle comments both when lower and upper exist and when they don't
 | 
				
			||||||
 | 
					a1 = "a"[
 | 
				
			||||||
 | 
					    # a
 | 
				
			||||||
 | 
					    1  # b
 | 
				
			||||||
 | 
					    :  # c
 | 
				
			||||||
 | 
					    2  # d
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					a2 = "a"[
 | 
				
			||||||
 | 
					    # a
 | 
				
			||||||
 | 
					      # b
 | 
				
			||||||
 | 
					    :  # c
 | 
				
			||||||
 | 
					      # d
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check all places where comments can exist
 | 
				
			||||||
 | 
					b1 = "b"[ # a
 | 
				
			||||||
 | 
					    # b
 | 
				
			||||||
 | 
					    1 # c
 | 
				
			||||||
 | 
					    # d
 | 
				
			||||||
 | 
					    : # e
 | 
				
			||||||
 | 
					    # f
 | 
				
			||||||
 | 
					    2 # g
 | 
				
			||||||
 | 
					    # h
 | 
				
			||||||
 | 
					    : # i
 | 
				
			||||||
 | 
					    # j
 | 
				
			||||||
 | 
					    3 # k
 | 
				
			||||||
 | 
					    # l
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Handle the spacing from the colon correctly with upper leading comments
 | 
				
			||||||
 | 
					c1 = "c"[
 | 
				
			||||||
 | 
					    1
 | 
				
			||||||
 | 
					    :  # e
 | 
				
			||||||
 | 
					    # f
 | 
				
			||||||
 | 
					    2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					c2 = "c"[
 | 
				
			||||||
 | 
					    1
 | 
				
			||||||
 | 
					    :  # e
 | 
				
			||||||
 | 
					    2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					c3 = "c"[
 | 
				
			||||||
 | 
					    1
 | 
				
			||||||
 | 
					    :
 | 
				
			||||||
 | 
					    # f
 | 
				
			||||||
 | 
					    2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					c4 = "c"[
 | 
				
			||||||
 | 
					    1
 | 
				
			||||||
 | 
					    : # f
 | 
				
			||||||
 | 
					    2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# End of line comments
 | 
				
			||||||
 | 
					d1 = "d"[ # comment
 | 
				
			||||||
 | 
					    :
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					d2 = "d"[  # comment
 | 
				
			||||||
 | 
					    1:
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					d3 = "d"[
 | 
				
			||||||
 | 
					    1  # comment
 | 
				
			||||||
 | 
					    :
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Spacing around the colon(s)
 | 
				
			||||||
 | 
					def a():
 | 
				
			||||||
 | 
					    ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					e00 = "e"[:]
 | 
				
			||||||
 | 
					e01 = "e"[:1]
 | 
				
			||||||
 | 
					e02 = "e"[: a()]
 | 
				
			||||||
 | 
					e10 = "e"[1:]
 | 
				
			||||||
 | 
					e11 = "e"[1:1]
 | 
				
			||||||
 | 
					e12 = "e"[1 : a()]
 | 
				
			||||||
 | 
					e20 = "e"[a() :]
 | 
				
			||||||
 | 
					e21 = "e"[a() : 1]
 | 
				
			||||||
 | 
					e22 = "e"[a() : a()]
 | 
				
			||||||
 | 
					e200 = "e"[a() :: ]
 | 
				
			||||||
 | 
					e201 = "e"[a() :: 1]
 | 
				
			||||||
 | 
					e202 = "e"[a() :: a()]
 | 
				
			||||||
 | 
					e210 = "e"[a() : 1 :]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Output
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					# Handle comments both when lower and upper exist and when they don't
 | 
				
			||||||
 | 
					a1 = "NOT_YET_IMPLEMENTED_STRING"[
 | 
				
			||||||
 | 
					    # a
 | 
				
			||||||
 | 
					    1  # b
 | 
				
			||||||
 | 
					    :  # c
 | 
				
			||||||
 | 
					    2  # d
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					a2 = "NOT_YET_IMPLEMENTED_STRING"[
 | 
				
			||||||
 | 
					    # a
 | 
				
			||||||
 | 
					    # b
 | 
				
			||||||
 | 
					    :  # c
 | 
				
			||||||
 | 
					    # d
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check all places where comments can exist
 | 
				
			||||||
 | 
					b1 = "NOT_YET_IMPLEMENTED_STRING"[  # a
 | 
				
			||||||
 | 
					    # b
 | 
				
			||||||
 | 
					    1  # c
 | 
				
			||||||
 | 
					    # d
 | 
				
			||||||
 | 
					    :  # e
 | 
				
			||||||
 | 
					    # f
 | 
				
			||||||
 | 
					    2  # g
 | 
				
			||||||
 | 
					    # h
 | 
				
			||||||
 | 
					    :  # i
 | 
				
			||||||
 | 
					    # j
 | 
				
			||||||
 | 
					    3  # k
 | 
				
			||||||
 | 
					    # l
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Handle the spacing from the colon correctly with upper leading comments
 | 
				
			||||||
 | 
					c1 = "NOT_YET_IMPLEMENTED_STRING"[
 | 
				
			||||||
 | 
					    1:  # e
 | 
				
			||||||
 | 
					    # f
 | 
				
			||||||
 | 
					    2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					c2 = "NOT_YET_IMPLEMENTED_STRING"[
 | 
				
			||||||
 | 
					    1:  # e
 | 
				
			||||||
 | 
					    2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					c3 = "NOT_YET_IMPLEMENTED_STRING"[
 | 
				
			||||||
 | 
					    1:
 | 
				
			||||||
 | 
					    # f
 | 
				
			||||||
 | 
					    2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					c4 = "NOT_YET_IMPLEMENTED_STRING"[
 | 
				
			||||||
 | 
					    1:  # f
 | 
				
			||||||
 | 
					    2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# End of line comments
 | 
				
			||||||
 | 
					d1 = "NOT_YET_IMPLEMENTED_STRING"[  # comment
 | 
				
			||||||
 | 
					    :
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					d2 = "NOT_YET_IMPLEMENTED_STRING"[  # comment
 | 
				
			||||||
 | 
					    1:
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					d3 = "NOT_YET_IMPLEMENTED_STRING"[
 | 
				
			||||||
 | 
					    1  # comment
 | 
				
			||||||
 | 
					    :
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Spacing around the colon(s)
 | 
				
			||||||
 | 
					def a():
 | 
				
			||||||
 | 
					    ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					e00 = "NOT_YET_IMPLEMENTED_STRING"[:]
 | 
				
			||||||
 | 
					e01 = "NOT_YET_IMPLEMENTED_STRING"[:1]
 | 
				
			||||||
 | 
					e02 = "NOT_YET_IMPLEMENTED_STRING"[ : NOT_IMPLEMENTED_call()]
 | 
				
			||||||
 | 
					e10 = "NOT_YET_IMPLEMENTED_STRING"[1:]
 | 
				
			||||||
 | 
					e11 = "NOT_YET_IMPLEMENTED_STRING"[1:1]
 | 
				
			||||||
 | 
					e12 = "NOT_YET_IMPLEMENTED_STRING"[1 : NOT_IMPLEMENTED_call()]
 | 
				
			||||||
 | 
					e20 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() :]
 | 
				
			||||||
 | 
					e21 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() : 1]
 | 
				
			||||||
 | 
					e22 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() : NOT_IMPLEMENTED_call()]
 | 
				
			||||||
 | 
					e200 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() : :]
 | 
				
			||||||
 | 
					e201 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() :: 1]
 | 
				
			||||||
 | 
					e202 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() :: NOT_IMPLEMENTED_call()]
 | 
				
			||||||
 | 
					e210 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() : 1 :]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -112,9 +112,8 @@ impl Token {
 | 
				
			||||||
        self.range.start()
 | 
					        self.range.start()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[allow(unused)]
 | 
					 | 
				
			||||||
    pub(crate) const fn end(&self) -> TextSize {
 | 
					    pub(crate) const fn end(&self) -> TextSize {
 | 
				
			||||||
        self.range.start()
 | 
					        self.range.end()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue