mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 02:38:25 +00:00
Improve slice formatting (#5922)
<!-- Thank you for contributing to Ruff! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary - Remove space when start of slice is empty - Treat unary op except `not` as simple expression ## Test Plan Add some simple tests for unary op expressions in slice Closes #5673
This commit is contained in:
parent
d351761f5d
commit
b866cbb33d
7 changed files with 33 additions and 212 deletions
|
@ -70,12 +70,15 @@ def a():
|
||||||
e00 = "e"[:]
|
e00 = "e"[:]
|
||||||
e01 = "e"[:1]
|
e01 = "e"[:1]
|
||||||
e02 = "e"[: a()]
|
e02 = "e"[: a()]
|
||||||
|
e03 = "e"[:-1]
|
||||||
e10 = "e"[1:]
|
e10 = "e"[1:]
|
||||||
e11 = "e"[1:1]
|
e11 = "e"[1:1]
|
||||||
e12 = "e"[1 : a()]
|
e12 = "e"[1 : a()]
|
||||||
|
e13 = "e"[1:-1]
|
||||||
e20 = "e"[a() :]
|
e20 = "e"[a() :]
|
||||||
e21 = "e"[a() : 1]
|
e21 = "e"[a() : 1]
|
||||||
e22 = "e"[a() : a()]
|
e22 = "e"[a() : a()]
|
||||||
|
e23 = "e"[a() : -1]
|
||||||
e200 = "e"[a() :: ]
|
e200 = "e"[a() :: ]
|
||||||
e201 = "e"[a() :: 1]
|
e201 = "e"[a() :: 1]
|
||||||
e202 = "e"[a() :: a()]
|
e202 = "e"[a() :: a()]
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use ruff_text_size::TextRange;
|
use ruff_text_size::TextRange;
|
||||||
use rustpython_parser::ast::ExprSlice;
|
use rustpython_parser::ast::{Expr, ExprSlice, ExprUnaryOp, Ranged, UnaryOp};
|
||||||
use rustpython_parser::ast::{Expr, Ranged};
|
|
||||||
|
|
||||||
use ruff_formatter::prelude::{hard_line_break, line_suffix_boundary, space, text};
|
use ruff_formatter::prelude::{hard_line_break, line_suffix_boundary, space, text};
|
||||||
use ruff_formatter::{write, Buffer, Format, FormatError, FormatResult};
|
use ruff_formatter::{write, Buffer, Format, FormatError, FormatResult};
|
||||||
|
@ -87,7 +86,7 @@ impl FormatNodeRule<ExprSlice> for FormatExprSlice {
|
||||||
// e201 = "e"[a() :: 1]
|
// e201 = "e"[a() :: 1]
|
||||||
// e202 = "e"[a() :: a()]
|
// e202 = "e"[a() :: a()]
|
||||||
// ```
|
// ```
|
||||||
if !all_simple {
|
if !all_simple && lower.is_some() {
|
||||||
space().fmt(f)?;
|
space().fmt(f)?;
|
||||||
}
|
}
|
||||||
text(":").fmt(f)?;
|
text(":").fmt(f)?;
|
||||||
|
@ -196,7 +195,17 @@ pub(crate) fn find_colons(
|
||||||
/// Determines whether this expression needs a space around the 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>
|
/// <https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#slices>
|
||||||
fn is_simple_expr(expr: &Expr) -> bool {
|
fn is_simple_expr(expr: &Expr) -> bool {
|
||||||
matches!(expr, Expr::Constant(_) | Expr::Name(_))
|
// Unary op expressions except `not` can be simple.
|
||||||
|
if let Some(ExprUnaryOp {
|
||||||
|
op: UnaryOp::UAdd | UnaryOp::USub | UnaryOp::Invert,
|
||||||
|
operand,
|
||||||
|
..
|
||||||
|
}) = expr.as_unary_op_expr()
|
||||||
|
{
|
||||||
|
is_simple_expr(operand)
|
||||||
|
} else {
|
||||||
|
matches!(expr, Expr::Constant(_) | Expr::Name(_))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) enum ExprSliceCommentSection {
|
pub(crate) enum ExprSliceCommentSection {
|
||||||
|
|
|
@ -323,32 +323,6 @@ last_call()
|
||||||
) # note: no trailing comma pre-3.6
|
) # note: no trailing comma pre-3.6
|
||||||
call(*gidgets[:2])
|
call(*gidgets[:2])
|
||||||
call(a, *gidgets[:2])
|
call(a, *gidgets[:2])
|
||||||
@@ -152,13 +159,13 @@
|
|
||||||
slice[0:1]
|
|
||||||
slice[0:1:2]
|
|
||||||
slice[:]
|
|
||||||
-slice[:-1]
|
|
||||||
+slice[ : -1]
|
|
||||||
slice[1:]
|
|
||||||
-slice[::-1]
|
|
||||||
+slice[ :: -1]
|
|
||||||
slice[d :: d + 1]
|
|
||||||
slice[:c, c - 1]
|
|
||||||
numpy[:, 0:1]
|
|
||||||
-numpy[:, :-1]
|
|
||||||
+numpy[:, : -1]
|
|
||||||
numpy[0, :]
|
|
||||||
numpy[:, i]
|
|
||||||
numpy[0, :2]
|
|
||||||
@@ -172,7 +179,7 @@
|
|
||||||
numpy[1 : c + 1, c]
|
|
||||||
numpy[-(c + 1) :, d]
|
|
||||||
numpy[:, l[-2]]
|
|
||||||
-numpy[:, ::-1]
|
|
||||||
+numpy[:, :: -1]
|
|
||||||
numpy[np.newaxis, :]
|
|
||||||
(str or None) if (sys.version_info[0] > (3,)) else (str or bytes or None)
|
|
||||||
{"2.7": dead, "3.7": long_live or die_hard}
|
|
||||||
@@ -207,25 +214,15 @@
|
@@ -207,25 +214,15 @@
|
||||||
)
|
)
|
||||||
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(
|
||||||
|
@ -596,13 +570,13 @@ slice[0]
|
||||||
slice[0:1]
|
slice[0:1]
|
||||||
slice[0:1:2]
|
slice[0:1:2]
|
||||||
slice[:]
|
slice[:]
|
||||||
slice[ : -1]
|
slice[:-1]
|
||||||
slice[1:]
|
slice[1:]
|
||||||
slice[ :: -1]
|
slice[::-1]
|
||||||
slice[d :: d + 1]
|
slice[d :: d + 1]
|
||||||
slice[:c, c - 1]
|
slice[:c, c - 1]
|
||||||
numpy[:, 0:1]
|
numpy[:, 0:1]
|
||||||
numpy[:, : -1]
|
numpy[:, :-1]
|
||||||
numpy[0, :]
|
numpy[0, :]
|
||||||
numpy[:, i]
|
numpy[:, i]
|
||||||
numpy[0, :2]
|
numpy[0, :2]
|
||||||
|
@ -616,7 +590,7 @@ numpy[:, [i]]
|
||||||
numpy[1 : c + 1, c]
|
numpy[1 : c + 1, c]
|
||||||
numpy[-(c + 1) :, d]
|
numpy[-(c + 1) :, d]
|
||||||
numpy[:, l[-2]]
|
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}
|
||||||
|
|
|
@ -211,7 +211,7 @@ d={'a':1,
|
||||||
# Comment 1
|
# Comment 1
|
||||||
|
|
||||||
# Comment 2
|
# Comment 2
|
||||||
@@ -17,30 +16,44 @@
|
@@ -17,26 +16,40 @@
|
||||||
|
|
||||||
# fmt: off
|
# fmt: off
|
||||||
def func_no_args():
|
def func_no_args():
|
||||||
|
@ -264,17 +264,12 @@ d={'a':1,
|
||||||
+ debug: bool = False,
|
+ debug: bool = False,
|
||||||
+ **kwargs,
|
+ **kwargs,
|
||||||
+) -> str:
|
+) -> str:
|
||||||
+ return text[number : -1]
|
+ return text[number:-1]
|
||||||
+
|
+
|
||||||
+
|
+
|
||||||
# fmt: on
|
# fmt: on
|
||||||
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""):
|
||||||
offset = attr.ib(default=attr.Factory(lambda: _r.uniform(1, 2)))
|
offset = attr.ib(default=attr.Factory(lambda: _r.uniform(1, 2)))
|
||||||
- assert task._cancel_stack[: len(old_stack)] == old_stack
|
|
||||||
+ assert task._cancel_stack[ : len(old_stack)] == old_stack
|
|
||||||
|
|
||||||
|
|
||||||
def spaces_types(
|
|
||||||
@@ -63,15 +76,15 @@
|
@@ -63,15 +76,15 @@
|
||||||
|
|
||||||
something = {
|
something = {
|
||||||
|
@ -445,13 +440,13 @@ def function_signature_stress_test(
|
||||||
debug: bool = False,
|
debug: bool = False,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> str:
|
) -> str:
|
||||||
return text[number : -1]
|
return text[number:-1]
|
||||||
|
|
||||||
|
|
||||||
# fmt: on
|
# fmt: on
|
||||||
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""):
|
||||||
offset = attr.ib(default=attr.Factory(lambda: _r.uniform(1, 2)))
|
offset = attr.ib(default=attr.Factory(lambda: _r.uniform(1, 2)))
|
||||||
assert task._cancel_stack[ : len(old_stack)] == old_stack
|
assert task._cancel_stack[: len(old_stack)] == old_stack
|
||||||
|
|
||||||
|
|
||||||
def spaces_types(
|
def spaces_types(
|
||||||
|
|
|
@ -117,21 +117,6 @@ def __await__(): return (yield)
|
||||||
|
|
||||||
|
|
||||||
def func_no_args():
|
def func_no_args():
|
||||||
@@ -41,12 +40,12 @@
|
|
||||||
debug: bool = False,
|
|
||||||
**kwargs,
|
|
||||||
) -> str:
|
|
||||||
- return text[number:-1]
|
|
||||||
+ return text[number : -1]
|
|
||||||
|
|
||||||
|
|
||||||
def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r""):
|
|
||||||
offset = attr.ib(default=attr.Factory(lambda: _r.uniform(10000, 200000)))
|
|
||||||
- assert task._cancel_stack[: len(old_stack)] == old_stack
|
|
||||||
+ assert task._cancel_stack[ : len(old_stack)] == old_stack
|
|
||||||
|
|
||||||
|
|
||||||
def spaces_types(
|
|
||||||
@@ -65,18 +64,14 @@
|
@@ -65,18 +64,14 @@
|
||||||
|
|
||||||
def spaces2(result=_core.Value(None)):
|
def spaces2(result=_core.Value(None)):
|
||||||
|
@ -220,12 +205,12 @@ def function_signature_stress_test(
|
||||||
debug: bool = False,
|
debug: bool = False,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> str:
|
) -> str:
|
||||||
return text[number : -1]
|
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""):
|
||||||
offset = attr.ib(default=attr.Factory(lambda: _r.uniform(10000, 200000)))
|
offset = attr.ib(default=attr.Factory(lambda: _r.uniform(10000, 200000)))
|
||||||
assert task._cancel_stack[ : len(old_stack)] == old_stack
|
assert task._cancel_stack[: len(old_stack)] == old_stack
|
||||||
|
|
||||||
|
|
||||||
def spaces_types(
|
def spaces_types(
|
||||||
|
|
|
@ -1,151 +0,0 @@
|
||||||
---
|
|
||||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/slices.py
|
|
||||||
---
|
|
||||||
## Input
|
|
||||||
|
|
||||||
```py
|
|
||||||
slice[a.b : c.d]
|
|
||||||
slice[d :: d + 1]
|
|
||||||
slice[d + 1 :: d]
|
|
||||||
slice[d::d]
|
|
||||||
slice[0]
|
|
||||||
slice[-1]
|
|
||||||
slice[:-1]
|
|
||||||
slice[::-1]
|
|
||||||
slice[:c, c - 1]
|
|
||||||
slice[c, c + 1, d::]
|
|
||||||
slice[ham[c::d] :: 1]
|
|
||||||
slice[ham[cheese**2 : -1] : 1 : 1, ham[1:2]]
|
|
||||||
slice[:-1:]
|
|
||||||
slice[lambda: None : lambda: None]
|
|
||||||
slice[lambda x, y, *args, really=2, **kwargs: None :, None::]
|
|
||||||
slice[1 or 2 : True and False]
|
|
||||||
slice[not so_simple : 1 < val <= 10]
|
|
||||||
slice[(1 for i in range(42)) : x]
|
|
||||||
slice[:: [i for i in range(42)]]
|
|
||||||
|
|
||||||
|
|
||||||
async def f():
|
|
||||||
slice[await x : [i async for i in arange(42)] : 42]
|
|
||||||
|
|
||||||
|
|
||||||
# These are from PEP-8:
|
|
||||||
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+offset : upper+offset]
|
|
||||||
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
|
|
||||||
ham[lower + offset : upper + offset]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Differences
|
|
||||||
|
|
||||||
```diff
|
|
||||||
--- Black
|
|
||||||
+++ Ruff
|
|
||||||
@@ -4,19 +4,19 @@
|
|
||||||
slice[d::d]
|
|
||||||
slice[0]
|
|
||||||
slice[-1]
|
|
||||||
-slice[:-1]
|
|
||||||
-slice[::-1]
|
|
||||||
+slice[ : -1]
|
|
||||||
+slice[ :: -1]
|
|
||||||
slice[:c, c - 1]
|
|
||||||
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 x, y, *args, really=2, **kwargs: None :, None::]
|
|
||||||
slice[1 or 2 : True and False]
|
|
||||||
slice[not so_simple : 1 < val <= 10]
|
|
||||||
slice[(1 for i in range(42)) : x]
|
|
||||||
-slice[:: [i for i in range(42)]]
|
|
||||||
+slice[ :: [i for i in range(42)]]
|
|
||||||
|
|
||||||
|
|
||||||
async def f():
|
|
||||||
@@ -27,5 +27,5 @@
|
|
||||||
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+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]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Ruff Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
slice[a.b : c.d]
|
|
||||||
slice[d :: d + 1]
|
|
||||||
slice[d + 1 :: d]
|
|
||||||
slice[d::d]
|
|
||||||
slice[0]
|
|
||||||
slice[-1]
|
|
||||||
slice[ : -1]
|
|
||||||
slice[ :: -1]
|
|
||||||
slice[:c, c - 1]
|
|
||||||
slice[c, c + 1, d::]
|
|
||||||
slice[ham[c::d] :: 1]
|
|
||||||
slice[ham[cheese**2 : -1] : 1 : 1, ham[1:2]]
|
|
||||||
slice[ : -1 :]
|
|
||||||
slice[lambda: None : lambda: None]
|
|
||||||
slice[lambda x, y, *args, really=2, **kwargs: None :, None::]
|
|
||||||
slice[1 or 2 : True and False]
|
|
||||||
slice[not so_simple : 1 < val <= 10]
|
|
||||||
slice[(1 for i in range(42)) : x]
|
|
||||||
slice[ :: [i for i in range(42)]]
|
|
||||||
|
|
||||||
|
|
||||||
async def f():
|
|
||||||
slice[await x : [i async for i in arange(42)] : 42]
|
|
||||||
|
|
||||||
|
|
||||||
# These are from PEP-8:
|
|
||||||
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+offset : upper+offset]
|
|
||||||
ham[ : upper_fn(x) : step_fn(x)], ham[ :: step_fn(x)]
|
|
||||||
ham[lower + offset : upper + offset]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
slice[a.b : c.d]
|
|
||||||
slice[d :: d + 1]
|
|
||||||
slice[d + 1 :: d]
|
|
||||||
slice[d::d]
|
|
||||||
slice[0]
|
|
||||||
slice[-1]
|
|
||||||
slice[:-1]
|
|
||||||
slice[::-1]
|
|
||||||
slice[:c, c - 1]
|
|
||||||
slice[c, c + 1, d::]
|
|
||||||
slice[ham[c::d] :: 1]
|
|
||||||
slice[ham[cheese**2 : -1] : 1 : 1, ham[1:2]]
|
|
||||||
slice[:-1:]
|
|
||||||
slice[lambda: None : lambda: None]
|
|
||||||
slice[lambda x, y, *args, really=2, **kwargs: None :, None::]
|
|
||||||
slice[1 or 2 : True and False]
|
|
||||||
slice[not so_simple : 1 < val <= 10]
|
|
||||||
slice[(1 for i in range(42)) : x]
|
|
||||||
slice[:: [i for i in range(42)]]
|
|
||||||
|
|
||||||
|
|
||||||
async def f():
|
|
||||||
slice[await x : [i async for i in arange(42)] : 42]
|
|
||||||
|
|
||||||
|
|
||||||
# These are from PEP-8:
|
|
||||||
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+offset : upper+offset]
|
|
||||||
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
|
|
||||||
ham[lower + offset : upper + offset]
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -76,12 +76,15 @@ def a():
|
||||||
e00 = "e"[:]
|
e00 = "e"[:]
|
||||||
e01 = "e"[:1]
|
e01 = "e"[:1]
|
||||||
e02 = "e"[: a()]
|
e02 = "e"[: a()]
|
||||||
|
e03 = "e"[:-1]
|
||||||
e10 = "e"[1:]
|
e10 = "e"[1:]
|
||||||
e11 = "e"[1:1]
|
e11 = "e"[1:1]
|
||||||
e12 = "e"[1 : a()]
|
e12 = "e"[1 : a()]
|
||||||
|
e13 = "e"[1:-1]
|
||||||
e20 = "e"[a() :]
|
e20 = "e"[a() :]
|
||||||
e21 = "e"[a() : 1]
|
e21 = "e"[a() : 1]
|
||||||
e22 = "e"[a() : a()]
|
e22 = "e"[a() : a()]
|
||||||
|
e23 = "e"[a() : -1]
|
||||||
e200 = "e"[a() :: ]
|
e200 = "e"[a() :: ]
|
||||||
e201 = "e"[a() :: 1]
|
e201 = "e"[a() :: 1]
|
||||||
e202 = "e"[a() :: a()]
|
e202 = "e"[a() :: a()]
|
||||||
|
@ -167,13 +170,16 @@ def a():
|
||||||
|
|
||||||
e00 = "e"[:]
|
e00 = "e"[:]
|
||||||
e01 = "e"[:1]
|
e01 = "e"[:1]
|
||||||
e02 = "e"[ : a()]
|
e02 = "e"[: a()]
|
||||||
|
e03 = "e"[:-1]
|
||||||
e10 = "e"[1:]
|
e10 = "e"[1:]
|
||||||
e11 = "e"[1:1]
|
e11 = "e"[1:1]
|
||||||
e12 = "e"[1 : a()]
|
e12 = "e"[1 : a()]
|
||||||
|
e13 = "e"[1:-1]
|
||||||
e20 = "e"[a() :]
|
e20 = "e"[a() :]
|
||||||
e21 = "e"[a() : 1]
|
e21 = "e"[a() : 1]
|
||||||
e22 = "e"[a() : a()]
|
e22 = "e"[a() : a()]
|
||||||
|
e23 = "e"[a() : -1]
|
||||||
e200 = "e"[a() : :]
|
e200 = "e"[a() : :]
|
||||||
e201 = "e"[a() :: 1]
|
e201 = "e"[a() :: 1]
|
||||||
e202 = "e"[a() :: a()]
|
e202 = "e"[a() :: a()]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue