Skip to content

Commit

Permalink
Support fmt: skip on clause headers
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaReiser committed Aug 15, 2023
1 parent 247979d commit dc28322
Show file tree
Hide file tree
Showing 16 changed files with 1,049 additions and 578 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
def http_error(status):
match status : # fmt: skip
case 400 : # fmt: skip
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _:
return "Something's wrong with the internet"

# point is an (x, y) tuple
match point:
case (0, 0): # fmt: skip
print("Origin")
case (0, y):
print(f"Y={y}")
case (x, 0):
print(f"X={x}")
case (x, y):
print(f"X={x}, Y={y}")
case _:
raise ValueError("Not a point")

class Point:
x: int
y: int

def location(point):
match point:
case Point(x=0, y =0 ) : # fmt: skip
print("Origin is the point's location.")
case Point(x=0, y=y):
print(f"Y={y} and the point is on the y-axis.")
case Point(x=x, y=0):
print(f"X={x} and the point is on the x-axis.")
case Point():
print("The point is located somewhere else on the plane.")
case _:
print("Not a point")


match points:
case []:
print("No points in the list.")
case [
Point(0, 0)
]: # fmt: skip
print("The origin is the only point in the list.")
case [Point(x, y)]:
print(f"A single point {x}, {y} is in the list.")
case [Point(0, y1), Point(0, y2)]:
print(f"Two points on the Y axis at {y1}, {y2} are in the list.")
case _:
print("Something else is found in the list.")


match test_variable:
case (
'warning',
code,
40
): # fmt: skip
print("A warning has been received.")
case ('error', code, _):
print(f"An error {code} occurred.")


match point:
case Point(x, y) if x == y: # fmt: skip
print(f"The point is located on the diagonal Y=X at {x}.")
case Point(x, y):
print(f"Point is not on the diagonal.")
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
for item in container:
if search_something(item):
# Found it!
process(item)
break
# leading comment
else : #fmt: skip
# Didn't find anything..
not_found_in_container()


while i < 10:
print(i)

# leading comment
else : #fmt: skip
# Didn't find anything..
print("I was already larger than 9")


try : # fmt: skip
some_call()
except Exception : # fmt: skip
pass
except : # fmt: skip
handle_exception()

else : # fmt: skip
pass
finally : # fmt: skip
finally_call()
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::comments::{trailing_comments, SourceComment};
use crate::comments::{trailing_comments, SourceComment, SuppressionKind};
use crate::expression::maybe_parenthesize_expression;
use crate::expression::parentheses::Parenthesize;
use crate::prelude::*;
use crate::verbatim::SuppressedClauseHeader;
use crate::{FormatNodeRule, PyFormatter};
use ruff_formatter::FormatRuleWithOptions;
use ruff_formatter::{write, Buffer, FormatResult};
Expand Down Expand Up @@ -46,33 +47,39 @@ impl FormatNodeRule<ExceptHandlerExceptHandler> for FormatExceptHandlerExceptHan
let comments_info = f.context().comments().clone();
let dangling_comments = comments_info.dangling_comments(item);

write!(
f,
[
text("except"),
match self.except_handler_kind {
ExceptHandlerKind::Regular => None,
ExceptHandlerKind::Starred => Some(text("*")),
}
]
)?;

if let Some(type_) = type_ {
if SuppressionKind::has_skip_comment(dangling_comments, f.context().source()) {
SuppressedClauseHeader::ExceptHandler(item).fmt(f)?;
} else {
write!(
f,
[
space(),
maybe_parenthesize_expression(type_, item, Parenthesize::IfBreaks)
text("except"),
match self.except_handler_kind {
ExceptHandlerKind::Regular => None,
ExceptHandlerKind::Starred => Some(text("*")),
}
]
)?;
if let Some(name) = name {
write!(f, [space(), text("as"), space(), name.format()])?;

if let Some(type_) = type_ {
write!(
f,
[
space(),
maybe_parenthesize_expression(type_, item, Parenthesize::IfBreaks)
]
)?;
if let Some(name) = name {
write!(f, [space(), text("as"), space(), name.format()])?;
}
}

text(":").fmt(f)?;
}

write!(
f,
[
text(":"),
trailing_comments(dangling_comments),
block_indent(&body.format()),
]
Expand Down
47 changes: 27 additions & 20 deletions crates/ruff_python_formatter/src/other/match_case.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use ruff_formatter::{write, Buffer, FormatResult};
use ruff_python_ast::MatchCase;

use crate::comments::{trailing_comments, SourceComment};
use crate::comments::{trailing_comments, SourceComment, SuppressionKind};
use crate::not_yet_implemented_custom_text;
use crate::prelude::*;
use crate::verbatim::SuppressedClauseHeader;
use crate::{FormatNodeRule, PyFormatter};

#[derive(Default)]
Expand All @@ -21,33 +22,39 @@ impl FormatNodeRule<MatchCase> for FormatMatchCase {
let comments = f.context().comments().clone();
let dangling_item_comments = comments.dangling_comments(item);

write!(
f,
[
text("case"),
space(),
format_with(|f: &mut PyFormatter| {
let comments = f.context().comments();
if SuppressionKind::has_skip_comment(dangling_item_comments, f.context().source()) {
SuppressedClauseHeader::MatchCase(item).fmt(f)?;
} else {
write!(
f,
[
text("case"),
space(),
format_with(|f: &mut PyFormatter| {
let comments = f.context().comments();

for comment in comments.leading_trailing_comments(pattern) {
// This is a lie, but let's go with it.
comment.mark_formatted();
}
for comment in comments.leading_trailing_comments(pattern) {
// This is a lie, but let's go with it.
comment.mark_formatted();
}

// Replace the whole `format_with` with `pattern.format()` once pattern formatting is implemented.
not_yet_implemented_custom_text("NOT_YET_IMPLEMENTED_Pattern", pattern).fmt(f)
}),
]
)?;
// Replace the whole `format_with` with `pattern.format()` once pattern formatting is implemented.
not_yet_implemented_custom_text("NOT_YET_IMPLEMENTED_Pattern", pattern)
.fmt(f)
}),
]
)?;

if let Some(guard) = guard {
write!(f, [space(), text("if"), space(), guard.format()])?;
}

if let Some(guard) = guard {
write!(f, [space(), text("if"), space(), guard.format()])?;
text(":").fmt(f)?;
}

write!(
f,
[
text(":"),
trailing_comments(dangling_item_comments),
block_indent(&body.format())
]
Expand Down
122 changes: 64 additions & 58 deletions crates/ruff_python_formatter/src/statement/stmt_class_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use ruff_formatter::write;
use ruff_python_ast::{Decorator, Ranged, StmtClassDef};
use ruff_python_trivia::lines_after_ignoring_trivia;

use crate::comments::{leading_comments, trailing_comments, SourceComment};
use crate::comments::{leading_comments, trailing_comments, SourceComment, SuppressionKind};
use crate::prelude::*;
use crate::statement::suite::SuiteKind;
use crate::verbatim::SuppressedClauseHeader;
use crate::FormatNodeRule;

#[derive(Default)]
Expand Down Expand Up @@ -36,71 +37,76 @@ impl FormatNodeRule<StmtClassDef> for FormatStmtClassDef {
}
.fmt(f)?;

write!(f, [text("class"), space(), name.format()])?;
if SuppressionKind::has_skip_comment(trailing_definition_comments, f.context().source()) {
SuppressedClauseHeader::Class(item).fmt(f)?;
} else {
write!(f, [text("class"), space(), name.format()])?;

if let Some(type_params) = type_params.as_deref() {
write!(f, [type_params.format()])?;
}
if let Some(type_params) = type_params.as_deref() {
write!(f, [type_params.format()])?;
}

if let Some(arguments) = arguments.as_deref() {
// Drop empty the arguments node entirely (i.e., remove the parentheses) if it is empty,
// e.g., given:
// ```python
// class A():
// ...
// ```
//
// Format as:
// ```python
// class A:
// ...
// ```
//
// However, preserve any dangling end-of-line comments, e.g., given:
// ```python
// class A( # comment
// ):
// ...
//
// Format as:
// ```python
// class A: # comment
// ...
// ```
//
// However, the arguments contain any dangling own-line comments, we retain the
// parentheses, e.g., given:
// ```python
// class A( # comment
// # comment
// ):
// ...
// ```
//
// Format as:
// ```python
// class A( # comment
// # comment
// ):
// ...
// ```
if arguments.is_empty()
&& comments
.dangling_comments(arguments)
.iter()
.all(|comment| comment.line_position().is_end_of_line())
{
let dangling = comments.dangling_comments(arguments);
write!(f, [trailing_comments(dangling)])?;
} else {
write!(f, [arguments.format()])?;
if let Some(arguments) = arguments.as_deref() {
// Drop empty the arguments node entirely (i.e., remove the parentheses) if it is empty,
// e.g., given:
// ```python
// class A():
// ...
// ```
//
// Format as:
// ```python
// class A:
// ...
// ```
//
// However, preserve any dangling end-of-line comments, e.g., given:
// ```python
// class A( # comment
// ):
// ...
//
// Format as:
// ```python
// class A: # comment
// ...
// ```
//
// However, the arguments contain any dangling own-line comments, we retain the
// parentheses, e.g., given:
// ```python
// class A( # comment
// # comment
// ):
// ...
// ```
//
// Format as:
// ```python
// class A( # comment
// # comment
// ):
// ...
// ```
if arguments.is_empty()
&& comments
.dangling_comments(arguments)
.iter()
.all(|comment| comment.line_position().is_end_of_line())
{
let dangling = comments.dangling_comments(arguments);
write!(f, [trailing_comments(dangling)])?;
} else {
write!(f, [arguments.format()])?;
}
}

write!(f, [text(":"),])?;
}

write!(
f,
[
text(":"),
trailing_comments(trailing_definition_comments),
block_indent(&body.format().with_options(SuiteKind::Class))
]
Expand Down
Loading

0 comments on commit dc28322

Please sign in to comment.