Add formatting for StmtMatch (#6286)

## Summary

This PR adds support for `StmtMatch` with subs for `MatchCase`.

## Test Plan

Add a few additional test cases around `match` statement, comments, line
breaks.

resolves: #6298
This commit is contained in:
Dhruv Manilawala 2023-08-08 18:48:49 +05:30 committed by GitHub
parent 87984e9ac7
commit 001aa486df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 882 additions and 444 deletions

View file

@ -0,0 +1,57 @@
# leading match comment
match foo: # dangling match comment
case "bar":
pass
# leading match comment
match ( # leading expr comment
# another leading expr comment
foo # trailing expr comment
# another trailing expr comment
): # dangling match comment
case "bar":
pass
# leading match comment
match ( # hello
foo # trailing expr comment
, # another
): # dangling match comment
case "bar":
pass
match [ # comment
first,
second,
third
]: # another comment
case ["a", "b", "c"]:
pass
match ( # comment
"a b c"
).split(): # another comment
case ["a", "b", "c"]:
pass
match ( # comment
# let's go
yield foo
): # another comment
case ["a", "b", "c"]:
pass
match aaaaaaaaahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh: # comment
case "sshhhhhhhh":
pass
def foo():
match inside_func: # comment
case "bar":
pass

View file

@ -63,7 +63,6 @@ pub(super) fn place_comment<'a>(
CommentPlacement::Default(comment) CommentPlacement::Default(comment)
} }
} }
AnyNodeRef::MatchCase(match_case) => handle_match_comment(comment, match_case, locator),
AnyNodeRef::ModModule(_) => { AnyNodeRef::ModModule(_) => {
handle_module_level_own_line_comment_before_class_or_function_comment(comment, locator) handle_module_level_own_line_comment_before_class_or_function_comment(comment, locator)
} }
@ -210,6 +209,10 @@ fn is_first_statement_in_body(statement: AnyNodeRef, has_body: AnyNodeRef) -> bo
are_same_optional(statement, body.first()) are_same_optional(statement, body.first())
} }
AnyNodeRef::StmtMatch(ast::StmtMatch { cases, .. }) => {
are_same_optional(statement, cases.first())
}
_ => false, _ => false,
} }
} }
@ -407,105 +410,6 @@ fn handle_own_line_comment_in_clause<'a>(
CommentPlacement::Default(comment) CommentPlacement::Default(comment)
} }
/// Handles leading comments in front of a match case or a trailing comment of the `match` statement.
/// ```python
/// match pt:
/// # Leading `case(x, y)` comment
/// case (x, y):
/// return Point3d(x, y, 0)
/// # Leading `case (x, y, z)` comment
/// case _:
/// ```
fn handle_match_comment<'a>(
comment: DecoratedComment<'a>,
match_case: &'a MatchCase,
locator: &Locator,
) -> CommentPlacement<'a> {
// Must be an own line comment after the last statement in a match case
if comment.line_position().is_end_of_line() || comment.following_node().is_some() {
return CommentPlacement::Default(comment);
}
// And its parent match statement.
let Some(match_stmt) = comment.enclosing_parent().and_then(AnyNodeRef::stmt_match) else {
return CommentPlacement::Default(comment);
};
// Get the next sibling (sibling traversal would be really nice)
let current_case_index = match_stmt
.cases
.iter()
.position(|case| case == match_case)
.expect("Expected case to belong to parent match statement.");
let next_case = match_stmt.cases.get(current_case_index + 1);
let comment_indentation = indentation_at_offset(comment.slice().range().start(), locator)
.unwrap_or_default()
.len();
let match_case_indentation = indentation(locator, match_case).unwrap().len();
if let Some(next_case) = next_case {
// The comment's indentation is less or equal to the `case` indention and there's a following
// `case` arm.
// ```python
// match pt:
// case (x, y):
// return Point3d(x, y, 0)
// # Leading `case (x, y, z)` comment
// case _:
// pass
// ```
// Attach the `comment` as leading comment to the next case.
if comment_indentation <= match_case_indentation {
CommentPlacement::leading(next_case, comment)
} else {
// Otherwise, delegate to `handle_trailing_body_comment`
// ```python
// match pt:
// case (x, y):
// return Point3d(x, y, 0)
// # Trailing case body comment
// case _:
// pass
// ```
CommentPlacement::Default(comment)
}
} else {
// Comment after the last statement in a match case...
let match_stmt_indentation = indentation(locator, match_stmt).unwrap_or_default().len();
if comment_indentation <= match_case_indentation
&& comment_indentation > match_stmt_indentation
{
// The comment's indent matches the `case` indent (or is larger than the `match`'s indent).
// ```python
// match pt:
// case (x, y):
// return Point3d(x, y, 0)
// case _:
// pass
// # Trailing match comment
// ```
// This is a trailing comment of the last case.
CommentPlacement::trailing(match_case, comment)
} else {
// Delegate to `handle_trailing_body_comment` because it's either a trailing indent
// for the last statement in the `case` body or a comment for the parent of the `match`
//
// ```python
// match pt:
// case (x, y):
// return Point3d(x, y, 0)
// case _:
// pass
// # trailing case comment
// ```
CommentPlacement::Default(comment)
}
}
}
/// Determine where to attach an own line comment after a branch depending on its indentation /// Determine where to attach an own line comment after a branch depending on its indentation
fn handle_own_line_comment_after_branch<'a>( fn handle_own_line_comment_after_branch<'a>(
comment: DecoratedComment<'a>, comment: DecoratedComment<'a>,

View file

@ -73,7 +73,6 @@ impl<'a> CommentsVisitor<'a> {
enclosing: enclosing_node, enclosing: enclosing_node,
preceding: self.preceding_node, preceding: self.preceding_node,
following: Some(node), following: Some(node),
parent: self.parents.iter().rev().nth(1).copied(),
line_position: text_position(*comment_range, self.source_code), line_position: text_position(*comment_range, self.source_code),
slice: self.source_code.slice(*comment_range), slice: self.source_code.slice(*comment_range),
}; };
@ -131,7 +130,6 @@ impl<'a> CommentsVisitor<'a> {
let comment = DecoratedComment { let comment = DecoratedComment {
enclosing: node, enclosing: node,
preceding: self.preceding_node, preceding: self.preceding_node,
parent: self.parents.last().copied(),
following: None, following: None,
line_position: text_position(*comment_range, self.source_code), line_position: text_position(*comment_range, self.source_code),
slice: self.source_code.slice(*comment_range), slice: self.source_code.slice(*comment_range),
@ -340,7 +338,6 @@ pub(super) struct DecoratedComment<'a> {
enclosing: AnyNodeRef<'a>, enclosing: AnyNodeRef<'a>,
preceding: Option<AnyNodeRef<'a>>, preceding: Option<AnyNodeRef<'a>>,
following: Option<AnyNodeRef<'a>>, following: Option<AnyNodeRef<'a>>,
parent: Option<AnyNodeRef<'a>>,
line_position: CommentLinePosition, line_position: CommentLinePosition,
slice: SourceCodeSlice, slice: SourceCodeSlice,
} }
@ -366,11 +363,6 @@ impl<'a> DecoratedComment<'a> {
self.enclosing self.enclosing
} }
/// Returns the parent of the enclosing node, if any
pub(super) fn enclosing_parent(&self) -> Option<AnyNodeRef<'a>> {
self.parent
}
/// Returns the slice into the source code. /// Returns the slice into the source code.
pub(super) fn slice(&self) -> &SourceCodeSlice { pub(super) fn slice(&self) -> &SourceCodeSlice {
&self.slice &self.slice

View file

@ -1,12 +1,45 @@
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult}; use ruff_formatter::{write, Buffer, FormatResult};
use ruff_python_ast::MatchCase; use ruff_python_ast::MatchCase;
use crate::expression::maybe_parenthesize_expression;
use crate::expression::parentheses::Parenthesize;
use crate::not_yet_implemented_custom_text;
use crate::prelude::*;
use crate::{FormatNodeRule, PyFormatter};
#[derive(Default)] #[derive(Default)]
pub struct FormatMatchCase; pub struct FormatMatchCase;
impl FormatNodeRule<MatchCase> for FormatMatchCase { impl FormatNodeRule<MatchCase> for FormatMatchCase {
fn fmt_fields(&self, item: &MatchCase, f: &mut PyFormatter) -> FormatResult<()> { fn fmt_fields(&self, item: &MatchCase, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [not_yet_implemented(item)]) let MatchCase {
range: _,
pattern: _,
guard,
body,
} = item;
write!(
f,
[
text("case"),
space(),
not_yet_implemented_custom_text("NOT_YET_IMPLEMENTED_Pattern"),
]
)?;
if let Some(guard) = guard {
write!(
f,
[
space(),
text("if"),
space(),
maybe_parenthesize_expression(guard, item, Parenthesize::IfBreaks)
]
)?;
}
write!(f, [text(":"), block_indent(&body.format())])
} }
} }

View file

@ -1,12 +1,49 @@
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult}; use ruff_formatter::{write, Buffer, FormatResult};
use ruff_python_ast::StmtMatch; use ruff_python_ast::StmtMatch;
use crate::comments::trailing_comments;
use crate::expression::maybe_parenthesize_expression;
use crate::expression::parentheses::Parenthesize;
use crate::prelude::*;
use crate::{FormatNodeRule, PyFormatter};
#[derive(Default)] #[derive(Default)]
pub struct FormatStmtMatch; pub struct FormatStmtMatch;
impl FormatNodeRule<StmtMatch> for FormatStmtMatch { impl FormatNodeRule<StmtMatch> for FormatStmtMatch {
fn fmt_fields(&self, item: &StmtMatch, f: &mut PyFormatter) -> FormatResult<()> { fn fmt_fields(&self, item: &StmtMatch, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [not_yet_implemented(item)]) let StmtMatch {
range: _,
subject,
cases,
} = item;
let comments = f.context().comments().clone();
let dangling_item_comments = comments.dangling_comments(item);
// There can be at most one dangling comment after the colon in a match statement.
debug_assert!(dangling_item_comments.len() <= 1);
write!(
f,
[
text("match"),
space(),
maybe_parenthesize_expression(subject, item, Parenthesize::IfBreaks),
text(":"),
trailing_comments(dangling_item_comments)
]
)?;
for case in cases {
write!(f, [block_indent(&case.format())])?;
}
Ok(())
}
fn fmt_dangling_comments(&self, _node: &StmtMatch, _f: &mut PyFormatter) -> FormatResult<()> {
// Handled as part of `fmt_fields`
Ok(())
} }
} }

View file

@ -156,180 +156,192 @@ match x:
```diff ```diff
--- Black --- Black
+++ Ruff +++ Ruff
@@ -1,144 +1,60 @@ @@ -2,143 +2,143 @@
# Cases sampled from Lib/test/test_patma.py
# case black_test_patma_098 # case black_test_patma_098
-match x: match x:
- case -0j: - case -0j:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_142 # case black_test_patma_142
-match x: match x:
- case bytes(z): - case bytes(z):
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_073 # case black_test_patma_073
-match x: match x:
- case 0 if 0: - case 0 if 0:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern if 0:
y = 0
- case 0 if 1: - case 0 if 1:
- y = 1 + case NOT_YET_IMPLEMENTED_Pattern if 1:
+NOT_YET_IMPLEMENTED_StmtMatch y = 1
# case black_test_patma_006 # case black_test_patma_006
-match 3: match 3:
- case 0 | 1 | 2 | 3: - case 0 | 1 | 2 | 3:
- x = True + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch x = True
# case black_test_patma_049 # case black_test_patma_049
-match x: match x:
- case [0, 1] | [1, 0]: - case [0, 1] | [1, 0]:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_check_sequence_then_mapping # case black_check_sequence_then_mapping
-match x: match x:
- case [*_]: - case [*_]:
- return "seq" + case NOT_YET_IMPLEMENTED_Pattern:
return "seq"
- case {}: - case {}:
- return "map" + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch return "map"
# case black_test_patma_035 # case black_test_patma_035
-match x: match x:
- case {0: [1, 2, {}]}: - case {0: [1, 2, {}]}:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
y = 0
- case {0: [1, 2, {}] | True} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}: - case {0: [1, 2, {}] | True} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}:
- y = 1 + case NOT_YET_IMPLEMENTED_Pattern:
y = 1
- case []: - case []:
- y = 2 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 2
# case black_test_patma_107 # case black_test_patma_107
-match x: match x:
- case 0.25 + 1.75j: - case 0.25 + 1.75j:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_097 # case black_test_patma_097
-match x: match x:
- case -0j: - case -0j:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_007 # case black_test_patma_007
-match 4: match 4:
- case 0 | 1 | 2 | 3: - case 0 | 1 | 2 | 3:
- x = True + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch x = True
# case black_test_patma_154 # case black_test_patma_154
-match x: match x:
- case 0 if x: - case 0 if x:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern if x:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_134 # case black_test_patma_134
-match x: match x:
- case {1: 0}: - case {1: 0}:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
y = 0
- case {0: 0}: - case {0: 0}:
- y = 1 + case NOT_YET_IMPLEMENTED_Pattern:
y = 1
- case {**z}: - case {**z}:
- y = 2 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 2
# case black_test_patma_185 # case black_test_patma_185
-match Seq(): match Seq():
- case [*_]: - case [*_]:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_063 # case black_test_patma_063
-match x: match x:
- case 1: - case 1:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
y = 0
- case 1: - case 1:
- y = 1 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 1
# case black_test_patma_248 # case black_test_patma_248
-match x: match x:
- case {"foo": bar}: - case {"foo": bar}:
- y = bar + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = bar
# case black_test_patma_019 # case black_test_patma_019
-match (0, 1, 2): match (0, 1, 2):
- case [0, 1, *x, 2]: - case [0, 1, *x, 2]:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_052 # case black_test_patma_052
-match x: match x:
- case [0]: - case [0]:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
y = 0
- case [1, 0] if (x := x[:0]): - case [1, 0] if (x := x[:0]):
- y = 1 + case NOT_YET_IMPLEMENTED_Pattern if x := x[:0]:
y = 1
- case [1, 0]: - case [1, 0]:
- y = 2 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 2
# case black_test_patma_191 # case black_test_patma_191
-match w: match w:
- case [x, y, *_]: - case [x, y, *_]:
- z = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch z = 0
# case black_test_patma_110 # case black_test_patma_110
-match x: match x:
- case -0.25 - 1.75j: - case -0.25 - 1.75j:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_151 # case black_test_patma_151
-match (x,): match (x,):
- case [y]: - case [y]:
- z = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch z = 0
# case black_test_patma_114 # case black_test_patma_114
-match x: match x:
- case A.B.C.D: - case A.B.C.D:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_232 # case black_test_patma_232
-match x: match x:
- case None: - case None:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_058 # case black_test_patma_058
-match x: match x:
- case 0: - case 0:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_233 # case black_test_patma_233
-match x: match x:
- case False: - case False:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_078 # case black_test_patma_078
-match x: match x:
- case []: - case []:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
y = 0
- case [""]: - case [""]:
- y = 1 + case NOT_YET_IMPLEMENTED_Pattern:
y = 1
- case "": - case "":
- y = 2 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 2
# case black_test_patma_156 # case black_test_patma_156
-match x: match x:
- case z: - case z:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_189 # case black_test_patma_189
-match w: match w:
- case [x, y, *rest]: - case [x, y, *rest]:
- z = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch z = 0
# case black_test_patma_042 # case black_test_patma_042
-match x: match x:
- case (0 as z) | (1 as z) | (2 as z) if z == x % 2: - case (0 as z) | (1 as z) | (2 as z) if z == x % 2:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern if z == x % 2:
+NOT_YET_IMPLEMENTED_StmtMatch y = 0
# case black_test_patma_034 # case black_test_patma_034
-match x: match x:
- case {0: [1, 2, {}]}: - case {0: [1, 2, {}]}:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
y = 0
- case {0: [1, 2, {}] | False} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}: - case {0: [1, 2, {}] | False} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}:
- y = 1 + case NOT_YET_IMPLEMENTED_Pattern:
y = 1
- case []: - case []:
- y = 2 + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch y = 2
``` ```
## Ruff Output ## Ruff Output
@ -338,63 +350,147 @@ match x:
# Cases sampled from Lib/test/test_patma.py # Cases sampled from Lib/test/test_patma.py
# case black_test_patma_098 # case black_test_patma_098
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
# case black_test_patma_142 # case black_test_patma_142
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
# case black_test_patma_073 # case black_test_patma_073
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern if 0:
y = 0
case NOT_YET_IMPLEMENTED_Pattern if 1:
y = 1
# case black_test_patma_006 # case black_test_patma_006
NOT_YET_IMPLEMENTED_StmtMatch match 3:
case NOT_YET_IMPLEMENTED_Pattern:
x = True
# case black_test_patma_049 # case black_test_patma_049
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
# case black_check_sequence_then_mapping # case black_check_sequence_then_mapping
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
return "seq"
case NOT_YET_IMPLEMENTED_Pattern:
return "map"
# case black_test_patma_035 # case black_test_patma_035
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
case NOT_YET_IMPLEMENTED_Pattern:
y = 1
case NOT_YET_IMPLEMENTED_Pattern:
y = 2
# case black_test_patma_107 # case black_test_patma_107
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
# case black_test_patma_097 # case black_test_patma_097
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
# case black_test_patma_007 # case black_test_patma_007
NOT_YET_IMPLEMENTED_StmtMatch match 4:
case NOT_YET_IMPLEMENTED_Pattern:
x = True
# case black_test_patma_154 # case black_test_patma_154
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern if x:
y = 0
# case black_test_patma_134 # case black_test_patma_134
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
case NOT_YET_IMPLEMENTED_Pattern:
y = 1
case NOT_YET_IMPLEMENTED_Pattern:
y = 2
# case black_test_patma_185 # case black_test_patma_185
NOT_YET_IMPLEMENTED_StmtMatch match Seq():
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
# case black_test_patma_063 # case black_test_patma_063
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
case NOT_YET_IMPLEMENTED_Pattern:
y = 1
# case black_test_patma_248 # case black_test_patma_248
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = bar
# case black_test_patma_019 # case black_test_patma_019
NOT_YET_IMPLEMENTED_StmtMatch match (0, 1, 2):
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
# case black_test_patma_052 # case black_test_patma_052
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
case NOT_YET_IMPLEMENTED_Pattern if x := x[:0]:
y = 1
case NOT_YET_IMPLEMENTED_Pattern:
y = 2
# case black_test_patma_191 # case black_test_patma_191
NOT_YET_IMPLEMENTED_StmtMatch match w:
case NOT_YET_IMPLEMENTED_Pattern:
z = 0
# case black_test_patma_110 # case black_test_patma_110
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
# case black_test_patma_151 # case black_test_patma_151
NOT_YET_IMPLEMENTED_StmtMatch match (x,):
case NOT_YET_IMPLEMENTED_Pattern:
z = 0
# case black_test_patma_114 # case black_test_patma_114
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
# case black_test_patma_232 # case black_test_patma_232
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
# case black_test_patma_058 # case black_test_patma_058
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
# case black_test_patma_233 # case black_test_patma_233
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
# case black_test_patma_078 # case black_test_patma_078
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
case NOT_YET_IMPLEMENTED_Pattern:
y = 1
case NOT_YET_IMPLEMENTED_Pattern:
y = 2
# case black_test_patma_156 # case black_test_patma_156
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
# case black_test_patma_189 # case black_test_patma_189
NOT_YET_IMPLEMENTED_StmtMatch match w:
case NOT_YET_IMPLEMENTED_Pattern:
z = 0
# case black_test_patma_042 # case black_test_patma_042
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern if z == x % 2:
y = 0
# case black_test_patma_034 # case black_test_patma_034
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
case NOT_YET_IMPLEMENTED_Pattern:
y = 1
case NOT_YET_IMPLEMENTED_Pattern:
y = 2
``` ```
## Black Output ## Black Output

View file

@ -131,139 +131,155 @@ match bar1:
```diff ```diff
--- Black --- Black
+++ Ruff +++ Ruff
@@ -1,119 +1,43 @@ @@ -1,13 +1,13 @@
import match import match
-match something: match something:
- case [a as b]: - case [a as b]:
- print(b) + case NOT_YET_IMPLEMENTED_Pattern:
print(b)
- case [a as b, c, d, e as f]: - case [a as b, c, d, e as f]:
- print(f) + case NOT_YET_IMPLEMENTED_Pattern:
print(f)
- case Point(a as b): - case Point(a as b):
- print(b) + case NOT_YET_IMPLEMENTED_Pattern:
print(b)
- case Point(int() as x, int() as y): - case Point(int() as x, int() as y):
- print(x, y) + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch print(x, y)
match = 1 @@ -15,40 +15,43 @@
case: int = re.match(something) case: int = re.match(something)
-match re.match(case): match re.match(case):
- case type("match", match): - case type("match", match):
- pass + case NOT_YET_IMPLEMENTED_Pattern:
pass
- case match: - case match:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch pass
def func(match: case, case: match) -> case: def func(match: case, case: match) -> case:
- match Something(): match Something():
- case func(match, case): - case func(match, case):
- ... + case NOT_YET_IMPLEMENTED_Pattern:
...
- case another: - case another:
- ... + case NOT_YET_IMPLEMENTED_Pattern:
+ NOT_YET_IMPLEMENTED_StmtMatch ...
-match maybe, multiple: match maybe, multiple:
- case perhaps, 5: - case perhaps, 5:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
pass
- case perhaps, 6,: - case perhaps, 6,:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch pass
-match more := (than, one), indeed,: -match more := (than, one), indeed,:
- case _, (5, 6): - case _, (5, 6):
- pass +match (
+ more := (than, one),
+ indeed,
+):
+ case NOT_YET_IMPLEMENTED_Pattern:
pass
- case [[5], (6)], [7],: - case [[5], (6)], [7],:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
pass
- case _: - case _:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch pass
-match a, *b, c: match a, *b, c:
- case [*_]: - case [*_]:
- assert "seq" == _ + case NOT_YET_IMPLEMENTED_Pattern:
assert "seq" == _
- case {}: - case {}:
- assert "map" == b + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch assert "map" == b
-match match( @@ -59,61 +62,47 @@
- case, ),
- match( case,
- match, case, match, looooooooooooooooooooooooooooooooooooong, match, case, match ):
- ),
- case,
-):
- case case( - case case(
- match=case, - match=case,
- case=re.match( - case=re.match(
- loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong - loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong
- ), - ),
- ): - ):
- pass + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch pass
-
- case [a as match]: - case [a as match]:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
pass
-
- case case: - case case:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
- pass
-
-match match:
- case case:
- pass
-
+NOT_YET_IMPLEMENTED_StmtMatch
-match a, *b(), c:
match match:
- case case:
+ case NOT_YET_IMPLEMENTED_Pattern:
pass
match a, *b(), c:
- case d, *f, g: - case d, *f, g:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
pass
-
-match something: match something:
- case { - case {
- "key": key as key_1, - "key": key as key_1,
- "password": PASS.ONE | PASS.TWO | PASS.THREE as password, - "password": PASS.ONE | PASS.TWO | PASS.THREE as password,
- }: - }:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
pass
- case {"maybe": something(complicated as this) as that}: - case {"maybe": something(complicated as this) as that}:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch pass
-match something: match something:
- case 1 as a: - case 1 as a:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch pass
-
- case 2 as b, 3 as c: - case 2 as b, 3 as c:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
pass
-
- case 4 as d, (5 as e), (6 | 7 as g), *h: - case 4 as d, (5 as e), (6 | 7 as g), *h:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch pass
-match bar1: match bar1:
- case Foo(aa=Callable() as aa, bb=int()): - case Foo(aa=Callable() as aa, bb=int()):
- print(bar1.aa, bar1.bb) + case NOT_YET_IMPLEMENTED_Pattern:
print(bar1.aa, bar1.bb)
- case _: - case _:
- print("no match", "\n") + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch print("no match", "\n")
-match bar1: match bar1:
- case Foo( - case Foo(
- normal=x, perhaps=[list, {"x": d, "y": 1.0}] as y, otherwise=something, q=t as u - normal=x, perhaps=[list, {"x": d, "y": 1.0}] as y, otherwise=something, q=t as u
- ): - ):
- pass + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch pass
``` ```
## Ruff Output ## Ruff Output
@ -271,47 +287,112 @@ match bar1:
```py ```py
import match import match
NOT_YET_IMPLEMENTED_StmtMatch match something:
case NOT_YET_IMPLEMENTED_Pattern:
print(b)
case NOT_YET_IMPLEMENTED_Pattern:
print(f)
case NOT_YET_IMPLEMENTED_Pattern:
print(b)
case NOT_YET_IMPLEMENTED_Pattern:
print(x, y)
match = 1 match = 1
case: int = re.match(something) case: int = re.match(something)
NOT_YET_IMPLEMENTED_StmtMatch match re.match(case):
case NOT_YET_IMPLEMENTED_Pattern:
pass
case NOT_YET_IMPLEMENTED_Pattern:
pass
def func(match: case, case: match) -> case: def func(match: case, case: match) -> case:
NOT_YET_IMPLEMENTED_StmtMatch match Something():
case NOT_YET_IMPLEMENTED_Pattern:
...
case NOT_YET_IMPLEMENTED_Pattern:
...
NOT_YET_IMPLEMENTED_StmtMatch match maybe, multiple:
case NOT_YET_IMPLEMENTED_Pattern:
pass
case NOT_YET_IMPLEMENTED_Pattern:
pass
NOT_YET_IMPLEMENTED_StmtMatch match (
more := (than, one),
indeed,
):
case NOT_YET_IMPLEMENTED_Pattern:
pass
case NOT_YET_IMPLEMENTED_Pattern:
pass
case NOT_YET_IMPLEMENTED_Pattern:
pass
NOT_YET_IMPLEMENTED_StmtMatch match a, *b, c:
case NOT_YET_IMPLEMENTED_Pattern:
assert "seq" == _
case NOT_YET_IMPLEMENTED_Pattern:
assert "map" == b
NOT_YET_IMPLEMENTED_StmtMatch match match(
case,
match(
match, case, match, looooooooooooooooooooooooooooooooooooong, match, case, match
),
case,
):
case NOT_YET_IMPLEMENTED_Pattern:
pass
case NOT_YET_IMPLEMENTED_Pattern:
pass
case NOT_YET_IMPLEMENTED_Pattern:
pass
NOT_YET_IMPLEMENTED_StmtMatch match match:
case NOT_YET_IMPLEMENTED_Pattern:
pass
NOT_YET_IMPLEMENTED_StmtMatch match a, *b(), c:
case NOT_YET_IMPLEMENTED_Pattern:
pass
NOT_YET_IMPLEMENTED_StmtMatch match something:
case NOT_YET_IMPLEMENTED_Pattern:
pass
case NOT_YET_IMPLEMENTED_Pattern:
pass
NOT_YET_IMPLEMENTED_StmtMatch match something:
case NOT_YET_IMPLEMENTED_Pattern:
pass
case NOT_YET_IMPLEMENTED_Pattern:
pass
case NOT_YET_IMPLEMENTED_Pattern:
pass
NOT_YET_IMPLEMENTED_StmtMatch match bar1:
case NOT_YET_IMPLEMENTED_Pattern:
print(bar1.aa, bar1.bb)
case NOT_YET_IMPLEMENTED_Pattern:
print("no match", "\n")
NOT_YET_IMPLEMENTED_StmtMatch match bar1:
case NOT_YET_IMPLEMENTED_Pattern:
pass
``` ```
## Black Output ## Black Output

View file

@ -119,49 +119,44 @@ with match() as match:
```diff ```diff
--- Black --- Black
+++ Ruff +++ Ruff
@@ -23,11 +23,7 @@ @@ -24,9 +24,9 @@
pygram.python_grammar,
] ]
- match match: match match:
- case case: - case case:
- match match: + case NOT_YET_IMPLEMENTED_Pattern:
match match:
- case case: - case case:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
+ NOT_YET_IMPLEMENTED_StmtMatch pass
if all(version.is_python2() for version in target_versions): if all(version.is_python2() for version in target_versions):
# Python 2-only code, so try Python 2 grammars. @@ -46,7 +46,7 @@
@@ -45,9 +41,7 @@
def test_patma_139(self): def test_patma_139(self):
x = False x = False
- match x: match x:
- case bool(z): - case bool(z):
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+ NOT_YET_IMPLEMENTED_StmtMatch y = 0
self.assertIs(x, False) self.assertIs(x, False)
self.assertEqual(y, 0) self.assertEqual(y, 0)
self.assertIs(z, x) @@ -73,14 +73,14 @@
@@ -72,16 +66,12 @@
def test_patma_155(self):
x = 0 x = 0
y = None y = None
- match x: match x:
- case 1e1000: - case 1e1000:
- y = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+ NOT_YET_IMPLEMENTED_StmtMatch y = 0
self.assertEqual(x, 0) self.assertEqual(x, 0)
self.assertIs(y, None) self.assertIs(y, None)
x = range(3) x = range(3)
- match x: match x:
- case [y, case as x, z]: - case [y, case as x, z]:
- w = 0 + case NOT_YET_IMPLEMENTED_Pattern:
+ NOT_YET_IMPLEMENTED_StmtMatch w = 0
# At least one of the above branches must have been taken, because every Python # At least one of the above branches must have been taken, because every Python
# version has exactly one of the two 'ASYNC_*' flags
``` ```
## Ruff Output ## Ruff Output
@ -192,7 +187,11 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]:
pygram.python_grammar, pygram.python_grammar,
] ]
NOT_YET_IMPLEMENTED_StmtMatch match match:
case NOT_YET_IMPLEMENTED_Pattern:
match match:
case NOT_YET_IMPLEMENTED_Pattern:
pass
if all(version.is_python2() for version in target_versions): if all(version.is_python2() for version in target_versions):
# Python 2-only code, so try Python 2 grammars. # Python 2-only code, so try Python 2 grammars.
@ -210,7 +209,9 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]:
def test_patma_139(self): def test_patma_139(self):
x = False x = False
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
self.assertIs(x, False) self.assertIs(x, False)
self.assertEqual(y, 0) self.assertEqual(y, 0)
self.assertIs(z, x) self.assertIs(z, x)
@ -235,12 +236,16 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]:
def test_patma_155(self): def test_patma_155(self):
x = 0 x = 0
y = None y = None
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
y = 0
self.assertEqual(x, 0) self.assertEqual(x, 0)
self.assertIs(y, None) self.assertIs(y, None)
x = range(3) x = range(3)
NOT_YET_IMPLEMENTED_StmtMatch match x:
case NOT_YET_IMPLEMENTED_Pattern:
w = 0
# At least one of the above branches must have been taken, because every Python # At least one of the above branches must have been taken, because every Python
# version has exactly one of the two 'ASYNC_*' flags # version has exactly one of the two 'ASYNC_*' flags

View file

@ -104,111 +104,129 @@ def where_is(point):
```diff ```diff
--- Black --- Black
+++ Ruff +++ Ruff
@@ -1,92 +1,27 @@ @@ -1,92 +1,92 @@
# Cases sampled from PEP 636 examples # Cases sampled from PEP 636 examples
-match command.split(): match command.split():
- case [action, obj]: - case [action, obj]:
- ... # interpret action, obj + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch ... # interpret action, obj
-match command.split(): match command.split():
- case [action]: - case [action]:
- ... # interpret single-verb action + case NOT_YET_IMPLEMENTED_Pattern:
... # interpret single-verb action
- case [action, obj]: - case [action, obj]:
- ... # interpret action, obj + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch ... # interpret action, obj
-match command.split(): match command.split():
- case ["quit"]: - case ["quit"]:
- print("Goodbye!") + case NOT_YET_IMPLEMENTED_Pattern:
- quit_game() print("Goodbye!")
quit_game()
- case ["look"]: - case ["look"]:
- current_room.describe() + case NOT_YET_IMPLEMENTED_Pattern:
current_room.describe()
- case ["get", obj]: - case ["get", obj]:
- character.get(obj, current_room) + case NOT_YET_IMPLEMENTED_Pattern:
character.get(obj, current_room)
- case ["go", direction]: - case ["go", direction]:
- current_room = current_room.neighbor(direction) + case NOT_YET_IMPLEMENTED_Pattern:
- # The rest of your commands go here current_room = current_room.neighbor(direction)
+NOT_YET_IMPLEMENTED_StmtMatch # The rest of your commands go here
-match command.split(): match command.split():
- case ["drop", *objects]: - case ["drop", *objects]:
- for obj in objects: + case NOT_YET_IMPLEMENTED_Pattern:
- character.drop(obj, current_room) for obj in objects:
- # The rest of your commands go here character.drop(obj, current_room)
+NOT_YET_IMPLEMENTED_StmtMatch # The rest of your commands go here
-match command.split(): match command.split():
- case ["quit"]: - case ["quit"]:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
pass
- case ["go", direction]: - case ["go", direction]:
- print("Going:", direction) + case NOT_YET_IMPLEMENTED_Pattern:
print("Going:", direction)
- case ["drop", *objects]: - case ["drop", *objects]:
- print("Dropping: ", *objects) + case NOT_YET_IMPLEMENTED_Pattern:
print("Dropping: ", *objects)
- case _: - case _:
- print(f"Sorry, I couldn't understand {command!r}") + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch print(f"Sorry, I couldn't understand {command!r}")
-match command.split(): match command.split():
- case ["north"] | ["go", "north"]: - case ["north"] | ["go", "north"]:
- current_room = current_room.neighbor("north") + case NOT_YET_IMPLEMENTED_Pattern:
current_room = current_room.neighbor("north")
- case ["get", obj] | ["pick", "up", obj] | ["pick", obj, "up"]: - case ["get", obj] | ["pick", "up", obj] | ["pick", obj, "up"]:
- ... # Code for picking up the given object + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch ... # Code for picking up the given object
-match command.split(): match command.split():
- case ["go", ("north" | "south" | "east" | "west")]: - case ["go", ("north" | "south" | "east" | "west")]:
- current_room = current_room.neighbor(...) + case NOT_YET_IMPLEMENTED_Pattern:
- # how do I know which direction to go? current_room = current_room.neighbor(...)
+NOT_YET_IMPLEMENTED_StmtMatch # how do I know which direction to go?
-match command.split(): match command.split():
- case ["go", ("north" | "south" | "east" | "west") as direction]: - case ["go", ("north" | "south" | "east" | "west") as direction]:
- current_room = current_room.neighbor(direction) + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch current_room = current_room.neighbor(direction)
-match command.split(): match command.split():
- case ["go", direction] if direction in current_room.exits: - case ["go", direction] if direction in current_room.exits:
- current_room = current_room.neighbor(direction) + case NOT_YET_IMPLEMENTED_Pattern if direction in current_room.exits:
current_room = current_room.neighbor(direction)
- case ["go", _]: - case ["go", _]:
- print("Sorry, you can't go that way") + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch print("Sorry, you can't go that way")
-match event.get(): match event.get():
- case Click(position=(x, y)): - case Click(position=(x, y)):
- handle_click_at(x, y) + case NOT_YET_IMPLEMENTED_Pattern:
handle_click_at(x, y)
- case KeyPress(key_name="Q") | Quit(): - case KeyPress(key_name="Q") | Quit():
- game.quit() + case NOT_YET_IMPLEMENTED_Pattern:
game.quit()
- case KeyPress(key_name="up arrow"): - case KeyPress(key_name="up arrow"):
- game.go_north() + case NOT_YET_IMPLEMENTED_Pattern:
game.go_north()
- case KeyPress(): - case KeyPress():
- pass # Ignore other keystrokes + case NOT_YET_IMPLEMENTED_Pattern:
pass # Ignore other keystrokes
- case other_event: - case other_event:
- raise ValueError(f"Unrecognized event: {other_event}") + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch raise ValueError(f"Unrecognized event: {other_event}")
-match event.get(): match event.get():
- case Click((x, y), button=Button.LEFT): # This is a left click - case Click((x, y), button=Button.LEFT): # This is a left click
- handle_click_at(x, y) + case NOT_YET_IMPLEMENTED_Pattern:
handle_click_at(x, y)
- case Click(): - case Click():
- pass # ignore other clicks + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch pass # ignore other clicks
def where_is(point): def where_is(point):
- match point: match point:
- case Point(x=0, y=0): - case Point(x=0, y=0):
- print("Origin") + case NOT_YET_IMPLEMENTED_Pattern:
print("Origin")
- case Point(x=0, y=y): - case Point(x=0, y=y):
- print(f"Y={y}") + case NOT_YET_IMPLEMENTED_Pattern:
print(f"Y={y}")
- case Point(x=x, y=0): - case Point(x=x, y=0):
- print(f"X={x}") + case NOT_YET_IMPLEMENTED_Pattern:
print(f"X={x}")
- case Point(): - case Point():
- print("Somewhere else") + case NOT_YET_IMPLEMENTED_Pattern:
print("Somewhere else")
- case _: - case _:
- print("Not a point") + case NOT_YET_IMPLEMENTED_Pattern:
+ NOT_YET_IMPLEMENTED_StmtMatch print("Not a point")
``` ```
## Ruff Output ## Ruff Output
@ -216,31 +234,96 @@ def where_is(point):
```py ```py
# Cases sampled from PEP 636 examples # Cases sampled from PEP 636 examples
NOT_YET_IMPLEMENTED_StmtMatch match command.split():
case NOT_YET_IMPLEMENTED_Pattern:
... # interpret action, obj
NOT_YET_IMPLEMENTED_StmtMatch match command.split():
case NOT_YET_IMPLEMENTED_Pattern:
... # interpret single-verb action
case NOT_YET_IMPLEMENTED_Pattern:
... # interpret action, obj
NOT_YET_IMPLEMENTED_StmtMatch match command.split():
case NOT_YET_IMPLEMENTED_Pattern:
print("Goodbye!")
quit_game()
case NOT_YET_IMPLEMENTED_Pattern:
current_room.describe()
case NOT_YET_IMPLEMENTED_Pattern:
character.get(obj, current_room)
case NOT_YET_IMPLEMENTED_Pattern:
current_room = current_room.neighbor(direction)
# The rest of your commands go here
NOT_YET_IMPLEMENTED_StmtMatch match command.split():
case NOT_YET_IMPLEMENTED_Pattern:
for obj in objects:
character.drop(obj, current_room)
# The rest of your commands go here
NOT_YET_IMPLEMENTED_StmtMatch match command.split():
case NOT_YET_IMPLEMENTED_Pattern:
pass
case NOT_YET_IMPLEMENTED_Pattern:
print("Going:", direction)
case NOT_YET_IMPLEMENTED_Pattern:
print("Dropping: ", *objects)
case NOT_YET_IMPLEMENTED_Pattern:
print(f"Sorry, I couldn't understand {command!r}")
NOT_YET_IMPLEMENTED_StmtMatch match command.split():
case NOT_YET_IMPLEMENTED_Pattern:
current_room = current_room.neighbor("north")
case NOT_YET_IMPLEMENTED_Pattern:
... # Code for picking up the given object
NOT_YET_IMPLEMENTED_StmtMatch match command.split():
case NOT_YET_IMPLEMENTED_Pattern:
current_room = current_room.neighbor(...)
# how do I know which direction to go?
NOT_YET_IMPLEMENTED_StmtMatch match command.split():
case NOT_YET_IMPLEMENTED_Pattern:
current_room = current_room.neighbor(direction)
NOT_YET_IMPLEMENTED_StmtMatch match command.split():
case NOT_YET_IMPLEMENTED_Pattern if direction in current_room.exits:
current_room = current_room.neighbor(direction)
case NOT_YET_IMPLEMENTED_Pattern:
print("Sorry, you can't go that way")
NOT_YET_IMPLEMENTED_StmtMatch match event.get():
case NOT_YET_IMPLEMENTED_Pattern:
handle_click_at(x, y)
case NOT_YET_IMPLEMENTED_Pattern:
game.quit()
case NOT_YET_IMPLEMENTED_Pattern:
game.go_north()
case NOT_YET_IMPLEMENTED_Pattern:
pass # Ignore other keystrokes
case NOT_YET_IMPLEMENTED_Pattern:
raise ValueError(f"Unrecognized event: {other_event}")
NOT_YET_IMPLEMENTED_StmtMatch match event.get():
case NOT_YET_IMPLEMENTED_Pattern:
handle_click_at(x, y)
case NOT_YET_IMPLEMENTED_Pattern:
pass # ignore other clicks
def where_is(point): def where_is(point):
NOT_YET_IMPLEMENTED_StmtMatch match point:
case NOT_YET_IMPLEMENTED_Pattern:
print("Origin")
case NOT_YET_IMPLEMENTED_Pattern:
print(f"Y={y}")
case NOT_YET_IMPLEMENTED_Pattern:
print(f"X={x}")
case NOT_YET_IMPLEMENTED_Pattern:
print("Somewhere else")
case NOT_YET_IMPLEMENTED_Pattern:
print("Not a point")
``` ```
## Black Output ## Black Output

View file

@ -65,22 +65,25 @@ match match(
```diff ```diff
--- Black --- Black
+++ Ruff +++ Ruff
@@ -1,35 +1,24 @@ @@ -1,35 +1,34 @@
-match something: match something:
- case b(): - case b():
- print(1 + 1) + case NOT_YET_IMPLEMENTED_Pattern:
print(1 + 1)
- case c( - case c(
- very_complex=True, perhaps_even_loooooooooooooooooooooooooooooooooooooong=-1 - very_complex=True, perhaps_even_loooooooooooooooooooooooooooooooooooooong=-1
- ): - ):
- print(1) + case NOT_YET_IMPLEMENTED_Pattern:
print(1)
- case c( - case c(
- very_complex=True, - very_complex=True,
- perhaps_even_loooooooooooooooooooooooooooooooooooooong=-1, - perhaps_even_loooooooooooooooooooooooooooooooooooooong=-1,
- ): - ):
- print(2) + case NOT_YET_IMPLEMENTED_Pattern:
print(2)
- case a: - case a:
- pass + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch pass
-match(arg) # comment -match(arg) # comment
+match( +match(
@ -106,18 +109,26 @@ match match(
+ something # fast + something # fast
+) +)
re.match() re.match()
-match match(): match match():
- case case( - case case(
- arg, # comment - arg, # comment
- ): - ):
- pass + case NOT_YET_IMPLEMENTED_Pattern:
+NOT_YET_IMPLEMENTED_StmtMatch pass
``` ```
## Ruff Output ## Ruff Output
```py ```py
NOT_YET_IMPLEMENTED_StmtMatch match something:
case NOT_YET_IMPLEMENTED_Pattern:
print(1 + 1)
case NOT_YET_IMPLEMENTED_Pattern:
print(1)
case NOT_YET_IMPLEMENTED_Pattern:
print(2)
case NOT_YET_IMPLEMENTED_Pattern:
pass
match( match(
arg # comment arg # comment
@ -140,7 +151,9 @@ re.match(
something # fast something # fast
) )
re.match() re.match()
NOT_YET_IMPLEMENTED_StmtMatch match match():
case NOT_YET_IMPLEMENTED_Pattern:
pass
``` ```
## Black Output ## Black Output

View file

@ -31,28 +31,39 @@ def http_status(status):
```diff ```diff
--- Black --- Black
+++ Ruff +++ Ruff
@@ -1,13 +1,2 @@ @@ -1,13 +1,10 @@
def http_status(status): def http_status(status):
- match status: match status:
- case 400: - case 400:
- return "Bad request" + case NOT_YET_IMPLEMENTED_Pattern:
return "Bad request"
- -
- case 401: - case 401:
- return "Unauthorized" + case NOT_YET_IMPLEMENTED_Pattern:
return "Unauthorized"
- -
- case 403: - case 403:
- return "Forbidden" + case NOT_YET_IMPLEMENTED_Pattern:
return "Forbidden"
- -
- case 404: - case 404:
- return "Not found" + case NOT_YET_IMPLEMENTED_Pattern:
+ NOT_YET_IMPLEMENTED_StmtMatch return "Not found"
``` ```
## Ruff Output ## Ruff Output
```py ```py
def http_status(status): def http_status(status):
NOT_YET_IMPLEMENTED_StmtMatch match status:
case NOT_YET_IMPLEMENTED_Pattern:
return "Bad request"
case NOT_YET_IMPLEMENTED_Pattern:
return "Unauthorized"
case NOT_YET_IMPLEMENTED_Pattern:
return "Forbidden"
case NOT_YET_IMPLEMENTED_Pattern:
return "Not found"
``` ```
## Black Output ## Black Output

View file

@ -0,0 +1,126 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/match.py
---
## Input
```py
# leading match comment
match foo: # dangling match comment
case "bar":
pass
# leading match comment
match ( # leading expr comment
# another leading expr comment
foo # trailing expr comment
# another trailing expr comment
): # dangling match comment
case "bar":
pass
# leading match comment
match ( # hello
foo # trailing expr comment
, # another
): # dangling match comment
case "bar":
pass
match [ # comment
first,
second,
third
]: # another comment
case ["a", "b", "c"]:
pass
match ( # comment
"a b c"
).split(): # another comment
case ["a", "b", "c"]:
pass
match ( # comment
# let's go
yield foo
): # another comment
case ["a", "b", "c"]:
pass
match aaaaaaaaahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh: # comment
case "sshhhhhhhh":
pass
def foo():
match inside_func: # comment
case "bar":
pass
```
## Output
```py
# leading match comment
match foo: # dangling match comment
case NOT_YET_IMPLEMENTED_Pattern:
pass
# leading match comment
match (
# leading expr comment
# another leading expr comment
foo # trailing expr comment
# another trailing expr comment
): # dangling match comment
case NOT_YET_IMPLEMENTED_Pattern:
pass
# leading match comment
match ( # hello
foo, # trailing expr comment # another
): # dangling match comment
case NOT_YET_IMPLEMENTED_Pattern:
pass
match [first, second, third]: # comment # another comment
case NOT_YET_IMPLEMENTED_Pattern:
pass
match (
# comment
"a b c"
).split(): # another comment
case NOT_YET_IMPLEMENTED_Pattern:
pass
match (
# comment
# let's go
yield foo
): # another comment
case NOT_YET_IMPLEMENTED_Pattern:
pass
match aaaaaaaaahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh: # comment
case NOT_YET_IMPLEMENTED_Pattern:
pass
def foo():
match inside_func: # comment
case NOT_YET_IMPLEMENTED_Pattern:
pass
```