diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/try.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/try.py new file mode 100644 index 0000000000..f50dcab4c4 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/try.py @@ -0,0 +1,72 @@ +try: + ... +except: + ... + +try: + ... +except (KeyError): # should remove brackets and be a single line + ... + + +try: # try + ... + # end of body +# before except +except (Exception, ValueError) as exc: # except line + ... +# before except 2 +except KeyError as key: # except line 2 + ... + # in body 2 +# before else +else: + ... +# before finally +finally: + ... + + + +# with line breaks +try: # try + ... + # end of body + +# before except +except (Exception, ValueError) as exc: # except line + ... + +# before except 2 +except KeyError as key: # except line 2 + ... + # in body 2 + +# before else +else: + ... + +# before finally +finally: + ... + + +# with line breaks +try: + ... + +except: + ... + + +try: + ... +except (Exception, Exception, Exception, Exception, Exception, Exception, Exception) as exc: # splits exception over multiple lines + ... + + +try: + ... +except: + a = 10 # trailing comment1 + b = 11 # trailing comment2 diff --git a/crates/ruff_python_formatter/src/comments/placement.rs b/crates/ruff_python_formatter/src/comments/placement.rs index 2f72f863d8..9e31caddbb 100644 --- a/crates/ruff_python_formatter/src/comments/placement.rs +++ b/crates/ruff_python_formatter/src/comments/placement.rs @@ -29,6 +29,7 @@ pub(super) fn place_comment<'a>( handle_trailing_body_comment, handle_trailing_end_of_line_body_comment, handle_trailing_end_of_line_condition_comment, + handle_trailing_end_of_line_except_comment, handle_module_level_own_line_comment_before_class_or_function_comment, handle_arguments_separator_comment, handle_trailing_binary_expression_left_or_operator_comment, @@ -158,44 +159,52 @@ fn handle_in_between_except_handlers_or_except_handler_and_else_or_finally_comme comment: DecoratedComment<'a>, locator: &Locator, ) -> CommentPlacement<'a> { - if comment.line_position().is_end_of_line() || comment.following_node().is_none() { + if comment.line_position().is_end_of_line() { return CommentPlacement::Default(comment); } - if let Some(AnyNodeRef::ExceptHandlerExceptHandler(except_handler)) = comment.preceding_node() { - // it now depends on the indentation level of the comment if it is a leading comment for e.g. - // the following `elif` or indeed a trailing comment of the previous body's last statement. - let comment_indentation = - whitespace::indentation_at_offset(locator, comment.slice().range().start()) - .map(str::len) - .unwrap_or_default(); + let (Some(AnyNodeRef::ExceptHandlerExceptHandler(preceding_except_handler)), Some(following)) = (comment.preceding_node(), comment.following_node()) else { + return CommentPlacement::Default(comment); + }; - if let Some(except_indentation) = - whitespace::indentation(locator, except_handler).map(str::len) + // it now depends on the indentation level of the comment if it is a leading comment for e.g. + // the following `finally` or indeed a trailing comment of the previous body's last statement. + let comment_indentation = + whitespace::indentation_at_offset(locator, comment.slice().range().start()) + .map(str::len) + .unwrap_or_default(); + + let Some(except_indentation) = + whitespace::indentation(locator, preceding_except_handler).map(str::len) else { - return if comment_indentation <= except_indentation { - // It has equal, or less indent than the `except` handler. It must be a comment - // of the following `finally` or `else` block - // - // ```python - // try: - // pass - // except Exception: - // print("noop") - // # leading - // finally: - // pass - // ``` - // Attach it to the `try` statement. - CommentPlacement::dangling(comment.enclosing_node(), comment) - } else { - // Delegate to `handle_trailing_body_comment` - CommentPlacement::Default(comment) - }; - } + return CommentPlacement::Default(comment); + }; + + if comment_indentation > except_indentation { + // Delegate to `handle_trailing_body_comment` + return CommentPlacement::Default(comment); } - CommentPlacement::Default(comment) + // It has equal, or less indent than the `except` handler. It must be a comment of a subsequent + // except handler or of the following `finally` or `else` block + // + // ```python + // try: + // pass + // except Exception: + // print("noop") + // # leading + // finally: + // pass + // ``` + + if following.is_except_handler() { + // Attach it to the following except handler (which has a node) as leading + CommentPlacement::leading(following, comment) + } else { + // No following except handler; attach it to the `try` statement.as dangling + CommentPlacement::dangling(comment.enclosing_node(), comment) + } } /// Handles own line comments between the last statement and the first statement of two bodies. @@ -668,6 +677,40 @@ fn handle_trailing_end_of_line_condition_comment<'a>( CommentPlacement::Default(comment) } +/// Handles end of line comments after the `:` of an except clause +/// +/// ```python +/// try: +/// ... +/// except: # comment +/// pass +/// ``` +/// +/// It attaches the comment as dangling comment to the enclosing except handler. +fn handle_trailing_end_of_line_except_comment<'a>( + comment: DecoratedComment<'a>, + _locator: &Locator, +) -> CommentPlacement<'a> { + let AnyNodeRef::ExceptHandlerExceptHandler(handler) = comment.enclosing_node() else { + return CommentPlacement::Default(comment); + }; + + // Must be an end of line comment + if comment.line_position().is_own_line() { + return CommentPlacement::Default(comment); + } + + let Some(first_body_statement) = handler.body.first() else { + return CommentPlacement::Default(comment); + }; + + if comment.slice().start() < first_body_statement.range().start() { + CommentPlacement::dangling(comment.enclosing_node(), comment) + } else { + CommentPlacement::Default(comment) + } +} + /// Attaches comments for the positional only arguments separator `/` or the keywords only arguments /// separator `*` as dangling comments to the enclosing [`Arguments`] node. /// diff --git a/crates/ruff_python_formatter/src/other/except_handler_except_handler.rs b/crates/ruff_python_formatter/src/other/except_handler_except_handler.rs index 338b686bc7..2e1c695217 100644 --- a/crates/ruff_python_formatter/src/other/except_handler_except_handler.rs +++ b/crates/ruff_python_formatter/src/other/except_handler_except_handler.rs @@ -1,5 +1,9 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; +use crate::comments::trailing_comments; +use crate::expression::parentheses::Parenthesize; +use crate::prelude::*; +use crate::{FormatNodeRule, PyFormatter}; use ruff_formatter::{write, Buffer, FormatResult}; +use ruff_python_ast::node::AstNode; use rustpython_parser::ast::ExceptHandlerExceptHandler; #[derive(Default)] @@ -11,6 +15,43 @@ impl FormatNodeRule for FormatExceptHandlerExceptHan item: &ExceptHandlerExceptHandler, f: &mut PyFormatter, ) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + let ExceptHandlerExceptHandler { + range: _, + type_, + name, + body, + } = item; + + let comments_info = f.context().comments().clone(); + let dangling_comments = comments_info.dangling_comments(item.as_any_node_ref()); + + write!(f, [text("except")])?; + + if let Some(type_) = type_ { + write!( + f, + [space(), type_.format().with_options(Parenthesize::IfBreaks)] + )?; + if let Some(name) = name { + write!(f, [space(), text("as"), space(), name.format()])?; + } + } + write!( + f, + [ + text(":"), + trailing_comments(dangling_comments), + block_indent(&body.format()) + ] + ) + } + + fn fmt_dangling_comments( + &self, + _node: &ExceptHandlerExceptHandler, + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // dangling comments are formatted as part of fmt_fields + Ok(()) } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_try.rs b/crates/ruff_python_formatter/src/statement/stmt_try.rs index faab829230..701fb8165b 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_try.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_try.rs @@ -1,17 +1,112 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; +use crate::comments; +use crate::comments::leading_alternate_branch_comments; +use crate::comments::SourceComment; +use crate::prelude::*; +use crate::statement::FormatRefWithRule; +use crate::statement::Stmt; +use crate::{FormatNodeRule, PyFormatter}; use ruff_formatter::{write, Buffer, FormatResult}; -use rustpython_parser::ast::StmtTry; +use ruff_python_ast::node::AstNode; +use rustpython_parser::ast::{ExceptHandler, Ranged, StmtTry, Suite}; #[derive(Default)] pub struct FormatStmtTry; +#[derive(Copy, Clone, Default)] +pub struct FormatExceptHandler; + +impl FormatRule> for FormatExceptHandler { + fn fmt( + &self, + item: &ExceptHandler, + f: &mut Formatter>, + ) -> FormatResult<()> { + match item { + ExceptHandler::ExceptHandler(x) => x.format().fmt(f), + } + } +} + +impl<'ast> AsFormat> for ExceptHandler { + type Format<'a> = FormatRefWithRule< + 'a, + ExceptHandler, + FormatExceptHandler, + PyFormatContext<'ast>, + > where Self: 'a; + + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new(self, FormatExceptHandler::default()) + } +} + impl FormatNodeRule for FormatStmtTry { fn fmt_fields(&self, item: &StmtTry, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + let StmtTry { + range: _, + body, + handlers, + orelse, + finalbody, + } = item; + + let comments_info = f.context().comments().clone(); + let mut dangling_comments = comments_info.dangling_comments(item.as_any_node_ref()); + + write!(f, [text("try:"), block_indent(&body.format())])?; + + let mut previous_node = body.last(); + + for handler in handlers { + let handler_comments = comments_info.leading_comments(handler); + write!( + f, + [ + leading_alternate_branch_comments(handler_comments, previous_node), + &handler.format() + ] + )?; + previous_node = match handler { + ExceptHandler::ExceptHandler(handler) => handler.body.last(), + }; + } + + (previous_node, dangling_comments) = + format_case("else", orelse, previous_node, dangling_comments, f)?; + + format_case("finally", finalbody, previous_node, dangling_comments, f)?; + + write!(f, [comments::dangling_comments(dangling_comments)]) } fn fmt_dangling_comments(&self, _node: &StmtTry, _f: &mut PyFormatter) -> FormatResult<()> { - // TODO(konstin): Needs node formatting or this leads to unstable formatting + // dangling comments are formatted as part of fmt_fields Ok(()) } } + +fn format_case<'a>( + name: &'static str, + body: &Suite, + previous_node: Option<&Stmt>, + dangling_comments: &'a [SourceComment], + f: &mut PyFormatter, +) -> FormatResult<(Option<&'a Stmt>, &'a [SourceComment])> { + Ok(if let Some(last) = body.last() { + let case_comments_start = + dangling_comments.partition_point(|comment| comment.slice().end() <= last.end()); + let (case_comments, rest) = dangling_comments.split_at(case_comments_start); + write!( + f, + [leading_alternate_branch_comments( + case_comments, + previous_node + )] + )?; + + write!(f, [text(name), text(":"), block_indent(&body.format())])?; + (None, rest) + } else { + (None, dangling_comments) + }) +} diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments.py.snap index 30b27344f0..ebd4a1b917 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments.py.snap @@ -108,7 +108,7 @@ async def wat(): ```diff --- Black +++ Ruff -@@ -9,16 +9,13 @@ +@@ -9,16 +9,16 @@ Possibly also many, many lines. """ @@ -122,15 +122,16 @@ async def wat(): +NOT_YET_IMPLEMENTED_StmtImport +NOT_YET_IMPLEMENTED_StmtImportFrom # some noqa comment --try: + try: - import fast --except ImportError: ++ NOT_YET_IMPLEMENTED_StmtImport + except ImportError: - import slow as fast -+NOT_YET_IMPLEMENTED_StmtTry ++ NOT_YET_IMPLEMENTED_StmtImport # Some comment before a function. -@@ -35,7 +32,7 @@ +@@ -35,7 +35,7 @@ Possibly many lines. """ # FIXME: Some comment about why this function is crap but still in production. @@ -139,7 +140,7 @@ async def wat(): if inner_imports.are_evil(): # Explains why we have this if. -@@ -82,8 +79,7 @@ +@@ -82,8 +82,7 @@ async def wat(): # This comment, for some reason \ # contains a trailing backslash. @@ -149,7 +150,7 @@ async def wat(): # Comment after ending a block. if result: print("A OK", file=sys.stdout) -@@ -93,4 +89,4 @@ +@@ -93,4 +92,4 @@ # Some closing comments. # Maybe Vim or Emacs directives for formatting. @@ -178,7 +179,10 @@ NOT_YET_IMPLEMENTED_StmtImport NOT_YET_IMPLEMENTED_StmtImport NOT_YET_IMPLEMENTED_StmtImportFrom # some noqa comment -NOT_YET_IMPLEMENTED_StmtTry +try: + NOT_YET_IMPLEMENTED_StmtImport +except ImportError: + NOT_YET_IMPLEMENTED_StmtImport # Some comment before a function. diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments5.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments5.py.snap index 2a8d41d0ae..28f4426951 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments5.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments5.py.snap @@ -85,17 +85,9 @@ if __name__ == "__main__": ```diff --- Black +++ Ruff -@@ -20,14 +20,9 @@ - with open(some_temp_file) as f: - data = f.read() - --try: -- with open(some_other_file) as w: -- w.write(data) -- --except OSError: -- print("problems") -+NOT_YET_IMPLEMENTED_StmtTry +@@ -27,7 +27,7 @@ + except OSError: + print("problems") -import sys +NOT_YET_IMPLEMENTED_StmtImport @@ -129,7 +121,12 @@ for i in range(100): with open(some_temp_file) as f: data = f.read() -NOT_YET_IMPLEMENTED_StmtTry +try: + with open(some_other_file) as w: + w.write(data) + +except OSError: + print("problems") NOT_YET_IMPLEMENTED_StmtImport diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip8.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip8.py.snap index 133a41b6cf..084370e171 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip8.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip8.py.snap @@ -74,7 +74,7 @@ async def test_async_with(): ```diff --- Black +++ Ruff -@@ -1,62 +1,55 @@ +@@ -1,62 +1,61 @@ # Make sure a leading comment is not removed. -def some_func( unformatted, args ): # fmt: skip +def some_func(unformatted, args): # fmt: skip @@ -134,12 +134,16 @@ async def test_async_with(): -try : # fmt: skip -- some_call() ++try: ++ # fmt: skip + some_call() -except UnformattedError as ex: # fmt: skip - handle_exception() -finally : # fmt: skip -- finally_call() -+NOT_YET_IMPLEMENTED_StmtTry ++except UnformattedError as ex: # fmt: skip ++ handle_exception() # fmt: skip ++finally: + finally_call() -with give_me_context( unformatted, args ): # fmt: skip @@ -202,7 +206,13 @@ async def test_async_for(): NOT_YET_IMPLEMENTED_StmtAsyncFor # fmt: skip -NOT_YET_IMPLEMENTED_StmtTry +try: + # fmt: skip + some_call() +except UnformattedError as ex: # fmt: skip + handle_exception() # fmt: skip +finally: + finally_call() with give_me_context(unformatted, args): # fmt: skip diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function2.py.snap index bcd7954313..3fd47e2167 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function2.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function2.py.snap @@ -65,7 +65,7 @@ with hmm_but_this_should_get_two_preceding_newlines(): ```diff --- Black +++ Ruff -@@ -32,34 +32,20 @@ +@@ -32,34 +32,28 @@ if os.name == "posix": @@ -76,18 +76,18 @@ with hmm_but_this_should_get_two_preceding_newlines(): pass - elif os.name == "nt": -- try: + try: - import msvcrt -- -- def i_should_be_followed_by_only_one_newline(): -- pass -+ NOT_YET_IMPLEMENTED_StmtTry ++ NOT_YET_IMPLEMENTED_StmtImport -- except ImportError: -- -- def i_should_be_followed_by_only_one_newline(): -- pass + def i_should_be_followed_by_only_one_newline(): + pass + + except ImportError: - + def i_should_be_followed_by_only_one_newline(): + pass + elif False: - class IHopeYouAreHavingALovelyDay: @@ -146,7 +146,15 @@ if os.name == "posix": def i_should_be_followed_by_only_one_newline(): pass elif os.name == "nt": - NOT_YET_IMPLEMENTED_StmtTry + try: + NOT_YET_IMPLEMENTED_StmtImport + + def i_should_be_followed_by_only_one_newline(): + pass + + except ImportError: + def i_should_be_followed_by_only_one_newline(): + pass elif False: class IHopeYouAreHavingALovelyDay: diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_except_parens.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_except_parens.py.snap index a845bf4af2..5990c185cd 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_except_parens.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_except_parens.py.snap @@ -47,77 +47,100 @@ except (some.really.really.really.looooooooooooooooooooooooooooooooong.module.ov ```diff --- Black +++ Ruff -@@ -1,42 +1,17 @@ - # These brackets are redundant, therefore remove. --try: -- a.something --except AttributeError as err: +@@ -2,7 +2,7 @@ + try: + a.something + except AttributeError as err: - raise err -+NOT_YET_IMPLEMENTED_StmtTry ++ NOT_YET_IMPLEMENTED_StmtRaise # This is tuple of exceptions. # Although this could be replaced with just the exception, - # we do not remove brackets to preserve AST. --try: -- a.something --except (AttributeError,) as err: +@@ -10,28 +10,26 @@ + try: + a.something + except (AttributeError,) as err: - raise err -+NOT_YET_IMPLEMENTED_StmtTry ++ NOT_YET_IMPLEMENTED_StmtRaise # This is a tuple of exceptions. Do not remove brackets. --try: -- a.something --except (AttributeError, ValueError) as err: + try: + a.something + except (AttributeError, ValueError) as err: - raise err -+NOT_YET_IMPLEMENTED_StmtTry ++ NOT_YET_IMPLEMENTED_StmtRaise # Test long variants. --try: -- a.something + try: + a.something -except ( - some.really.really.really.looooooooooooooooooooooooooooooooong.module.over89.chars.Error -) as err: - raise err -+NOT_YET_IMPLEMENTED_StmtTry ++except some.really.really.really.looooooooooooooooooooooooooooooooong.module.over89.chars.Error as err: ++ NOT_YET_IMPLEMENTED_StmtRaise --try: -- a.something --except ( -- some.really.really.really.looooooooooooooooooooooooooooooooong.module.over89.chars.Error, --) as err: + try: + a.something + except ( + some.really.really.really.looooooooooooooooooooooooooooooooong.module.over89.chars.Error, + ) as err: - raise err -+NOT_YET_IMPLEMENTED_StmtTry ++ NOT_YET_IMPLEMENTED_StmtRaise --try: -- a.something --except ( -- some.really.really.really.looooooooooooooooooooooooooooooooong.module.over89.chars.Error, -- some.really.really.really.looooooooooooooooooooooooooooooooong.module.over89.chars.Error, --) as err: + try: + a.something +@@ -39,4 +37,4 @@ + some.really.really.really.looooooooooooooooooooooooooooooooong.module.over89.chars.Error, + some.really.really.really.looooooooooooooooooooooooooooooooong.module.over89.chars.Error, + ) as err: - raise err -+NOT_YET_IMPLEMENTED_StmtTry ++ NOT_YET_IMPLEMENTED_StmtRaise ``` ## Ruff Output ```py # These brackets are redundant, therefore remove. -NOT_YET_IMPLEMENTED_StmtTry +try: + a.something +except AttributeError as err: + NOT_YET_IMPLEMENTED_StmtRaise # This is tuple of exceptions. # Although this could be replaced with just the exception, # we do not remove brackets to preserve AST. -NOT_YET_IMPLEMENTED_StmtTry +try: + a.something +except (AttributeError,) as err: + NOT_YET_IMPLEMENTED_StmtRaise # This is a tuple of exceptions. Do not remove brackets. -NOT_YET_IMPLEMENTED_StmtTry +try: + a.something +except (AttributeError, ValueError) as err: + NOT_YET_IMPLEMENTED_StmtRaise # Test long variants. -NOT_YET_IMPLEMENTED_StmtTry +try: + a.something +except some.really.really.really.looooooooooooooooooooooooooooooooong.module.over89.chars.Error as err: + NOT_YET_IMPLEMENTED_StmtRaise -NOT_YET_IMPLEMENTED_StmtTry +try: + a.something +except ( + some.really.really.really.looooooooooooooooooooooooooooooooong.module.over89.chars.Error, +) as err: + NOT_YET_IMPLEMENTED_StmtRaise -NOT_YET_IMPLEMENTED_StmtTry +try: + a.something +except ( + some.really.really.really.looooooooooooooooooooooooooooooooong.module.over89.chars.Error, + some.really.really.really.looooooooooooooooooooooooooooooooong.module.over89.chars.Error, +) as err: + NOT_YET_IMPLEMENTED_StmtRaise ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_parens.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_parens.py.snap index bb59ae6651..2ba7a34a5a 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_parens.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_parens.py.snap @@ -67,22 +67,18 @@ def example8(): ```diff --- Black +++ Ruff -@@ -8,13 +8,7 @@ - - async def show_status(): +@@ -10,9 +10,7 @@ while True: -- try: -- if report_host: + try: + if report_host: - data = ( - f"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - ).encode() -- except Exception as e: -- pass -+ NOT_YET_IMPLEMENTED_StmtTry ++ data = (NOT_YET_IMPLEMENTED_ExprJoinedStr).encode() + except Exception as e: + pass - - def example(): -@@ -30,15 +24,11 @@ +@@ -30,15 +28,11 @@ def example2(): @@ -100,7 +96,7 @@ def example8(): def example4(): -@@ -50,35 +40,11 @@ +@@ -50,35 +44,11 @@ def example6(): @@ -153,7 +149,11 @@ data = ( async def show_status(): while True: - NOT_YET_IMPLEMENTED_StmtTry + try: + if report_host: + data = (NOT_YET_IMPLEMENTED_ExprJoinedStr).encode() + except Exception as e: + pass def example(): diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__try.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__try.py.snap new file mode 100644 index 0000000000..e0a6fa67b0 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__try.py.snap @@ -0,0 +1,167 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/try.py +--- +## Input +```py +try: + ... +except: + ... + +try: + ... +except (KeyError): # should remove brackets and be a single line + ... + + +try: # try + ... + # end of body +# before except +except (Exception, ValueError) as exc: # except line + ... +# before except 2 +except KeyError as key: # except line 2 + ... + # in body 2 +# before else +else: + ... +# before finally +finally: + ... + + + +# with line breaks +try: # try + ... + # end of body + +# before except +except (Exception, ValueError) as exc: # except line + ... + +# before except 2 +except KeyError as key: # except line 2 + ... + # in body 2 + +# before else +else: + ... + +# before finally +finally: + ... + + +# with line breaks +try: + ... + +except: + ... + + +try: + ... +except (Exception, Exception, Exception, Exception, Exception, Exception, Exception) as exc: # splits exception over multiple lines + ... + + +try: + ... +except: + a = 10 # trailing comment1 + b = 11 # trailing comment2 +``` + +## Output +```py +try: + ... +except: + ... + +try: + ... +except KeyError: # should remove brackets and be a single line + ... + + +try: + # try + ... + # end of body +# before except +except (Exception, ValueError) as exc: # except line + ... +# before except 2 +except KeyError as key: # except line 2 + ... + # in body 2 +# before else +else: + ... +# before finally +finally: + ... + + +# with line breaks +try: + # try + ... + # end of body + +# before except +except (Exception, ValueError) as exc: # except line + ... + +# before except 2 +except KeyError as key: # except line 2 + ... + # in body 2 + +# before else +else: + ... + +# before finally +finally: + ... + + +# with line breaks +try: + ... + +except: + ... + + +try: + ... +except ( + Exception, + Exception, + Exception, + Exception, + Exception, + Exception, + Exception, +) as exc: # splits exception over multiple lines + ... + + +try: + ... +except: + a = 10 # trailing comment1 + b = 11 # trailing comment2 +``` + + +