mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-23 13:05:58 +00:00
Range formatting API (#9635)
This commit is contained in:
parent
6bb126415d
commit
ce14f4dea5
65 changed files with 3273 additions and 762 deletions
|
@ -1,5 +1,7 @@
|
|||
use std::borrow::Cow;
|
||||
use std::fmt::{Formatter, Write};
|
||||
use std::io::BufReader;
|
||||
use std::ops::Range;
|
||||
use std::path::Path;
|
||||
use std::{fmt, fs};
|
||||
|
||||
|
@ -8,8 +10,10 @@ use similar::TextDiff;
|
|||
use crate::normalizer::Normalizer;
|
||||
use ruff_formatter::FormatOptions;
|
||||
use ruff_python_ast::comparable::ComparableMod;
|
||||
use ruff_python_formatter::{format_module_source, PreviewMode, PyFormatOptions};
|
||||
use ruff_python_formatter::{format_module_source, format_range, PreviewMode, PyFormatOptions};
|
||||
use ruff_python_parser::{parse, AsMode};
|
||||
use ruff_source_file::{LineIndex, OneIndexed};
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
|
||||
mod normalizer;
|
||||
|
||||
|
@ -28,12 +32,65 @@ fn black_compatibility() {
|
|||
PyFormatOptions::from_extension(input_path)
|
||||
};
|
||||
|
||||
let printed = format_module_source(&content, options.clone()).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Formatting of {} to succeed but encountered error {err}",
|
||||
input_path.display()
|
||||
)
|
||||
});
|
||||
let first_line = content.lines().next().unwrap_or_default();
|
||||
let formatted_code = if first_line.starts_with("# flags:")
|
||||
&& first_line.contains("--line-ranges=")
|
||||
{
|
||||
let line_index = LineIndex::from_source_text(&content);
|
||||
|
||||
let ranges = first_line
|
||||
.split_ascii_whitespace()
|
||||
.filter_map(|chunk| {
|
||||
let (_, lines) = chunk.split_once("--line-ranges=")?;
|
||||
let (lower, upper) = lines.split_once('-')?;
|
||||
|
||||
let lower = lower
|
||||
.parse::<OneIndexed>()
|
||||
.expect("Expected a valid line number");
|
||||
let upper = upper
|
||||
.parse::<OneIndexed>()
|
||||
.expect("Expected a valid line number");
|
||||
|
||||
let range_start = line_index.line_start(lower, &content);
|
||||
let range_end = line_index.line_end(upper, &content);
|
||||
|
||||
Some(TextRange::new(range_start, range_end))
|
||||
})
|
||||
.rev();
|
||||
|
||||
let mut formatted_code = content.clone();
|
||||
|
||||
for range in ranges {
|
||||
let formatted =
|
||||
format_range(&content, range, options.clone()).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Range-formatting of {} to succeed but encountered error {err}",
|
||||
input_path.display()
|
||||
)
|
||||
});
|
||||
|
||||
let range = formatted.source_range();
|
||||
|
||||
formatted_code.replace_range(Range::<usize>::from(range), formatted.as_code());
|
||||
}
|
||||
|
||||
// We can't do stability checks for range formatting because we don't know the updated rangs.
|
||||
|
||||
formatted_code
|
||||
} else {
|
||||
let printed = format_module_source(&content, options.clone()).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Formatting of {} to succeed but encountered error {err}",
|
||||
input_path.display()
|
||||
)
|
||||
});
|
||||
|
||||
let formatted_code = printed.into_code();
|
||||
|
||||
ensure_stability_when_formatting_twice(&formatted_code, &options, input_path);
|
||||
|
||||
formatted_code
|
||||
};
|
||||
|
||||
let extension = input_path
|
||||
.extension()
|
||||
|
@ -43,10 +100,7 @@ fn black_compatibility() {
|
|||
let expected_output = fs::read_to_string(&expected_path)
|
||||
.unwrap_or_else(|_| panic!("Expected Black output file '{expected_path:?}' to exist"));
|
||||
|
||||
let formatted_code = printed.as_code();
|
||||
|
||||
ensure_unchanged_ast(&content, formatted_code, &options, input_path);
|
||||
ensure_stability_when_formatting_twice(formatted_code, &options, input_path);
|
||||
ensure_unchanged_ast(&content, &formatted_code, &options, input_path);
|
||||
|
||||
if formatted_code == expected_output {
|
||||
// Black and Ruff formatting matches. Delete any existing snapshot files because the Black output
|
||||
|
@ -88,7 +142,7 @@ fn black_compatibility() {
|
|||
|
||||
write!(snapshot, "{}", Header::new("Black Differences")).unwrap();
|
||||
|
||||
let diff = TextDiff::from_lines(expected_output.as_str(), formatted_code)
|
||||
let diff = TextDiff::from_lines(expected_output.as_str(), &formatted_code)
|
||||
.unified_diff()
|
||||
.header("Black", "Ruff")
|
||||
.to_string();
|
||||
|
@ -124,12 +178,7 @@ fn format() {
|
|||
let content = fs::read_to_string(input_path).unwrap();
|
||||
|
||||
let options = PyFormatOptions::from_extension(input_path);
|
||||
let printed =
|
||||
format_module_source(&content, options.clone()).expect("Formatting to succeed");
|
||||
let formatted_code = printed.as_code();
|
||||
|
||||
ensure_unchanged_ast(&content, formatted_code, &options, input_path);
|
||||
ensure_stability_when_formatting_twice(formatted_code, &options, input_path);
|
||||
let formatted_code = format_file(&content, &options, input_path);
|
||||
|
||||
let mut snapshot = format!("## Input\n{}", CodeFrame::new("python", &content));
|
||||
|
||||
|
@ -142,12 +191,7 @@ fn format() {
|
|||
writeln!(snapshot, "## Outputs").unwrap();
|
||||
|
||||
for (i, options) in options.into_iter().enumerate() {
|
||||
let printed =
|
||||
format_module_source(&content, options.clone()).expect("Formatting to succeed");
|
||||
let formatted_code = printed.as_code();
|
||||
|
||||
ensure_unchanged_ast(&content, formatted_code, &options, input_path);
|
||||
ensure_stability_when_formatting_twice(formatted_code, &options, input_path);
|
||||
let formatted_code = format_file(&content, &options, input_path);
|
||||
|
||||
writeln!(
|
||||
snapshot,
|
||||
|
@ -164,16 +208,7 @@ fn format() {
|
|||
|
||||
// We want to capture the differences in the preview style in our fixtures
|
||||
let options_preview = options.with_preview(PreviewMode::Enabled);
|
||||
let printed_preview = format_module_source(&content, options_preview.clone())
|
||||
.expect("Formatting to succeed");
|
||||
let formatted_preview = printed_preview.as_code();
|
||||
|
||||
ensure_unchanged_ast(&content, formatted_preview, &options_preview, input_path);
|
||||
ensure_stability_when_formatting_twice(
|
||||
formatted_preview,
|
||||
&options_preview,
|
||||
input_path,
|
||||
);
|
||||
let formatted_preview = format_file(&content, &options_preview, input_path);
|
||||
|
||||
if formatted_code != formatted_preview {
|
||||
// Having both snapshots makes it hard to see the difference, so we're keeping only
|
||||
|
@ -183,7 +218,7 @@ fn format() {
|
|||
"#### Preview changes\n{}",
|
||||
CodeFrame::new(
|
||||
"diff",
|
||||
TextDiff::from_lines(formatted_code, formatted_preview)
|
||||
TextDiff::from_lines(&formatted_code, &formatted_preview)
|
||||
.unified_diff()
|
||||
.header("Stable", "Preview")
|
||||
)
|
||||
|
@ -194,12 +229,7 @@ fn format() {
|
|||
} else {
|
||||
// We want to capture the differences in the preview style in our fixtures
|
||||
let options_preview = options.with_preview(PreviewMode::Enabled);
|
||||
let printed_preview = format_module_source(&content, options_preview.clone())
|
||||
.expect("Formatting to succeed");
|
||||
let formatted_preview = printed_preview.as_code();
|
||||
|
||||
ensure_unchanged_ast(&content, formatted_preview, &options_preview, input_path);
|
||||
ensure_stability_when_formatting_twice(formatted_preview, &options_preview, input_path);
|
||||
let formatted_preview = format_file(&content, &options_preview, input_path);
|
||||
|
||||
if formatted_code == formatted_preview {
|
||||
writeln!(
|
||||
|
@ -217,7 +247,7 @@ fn format() {
|
|||
CodeFrame::new("python", &formatted_code),
|
||||
CodeFrame::new(
|
||||
"diff",
|
||||
TextDiff::from_lines(formatted_code, formatted_preview)
|
||||
TextDiff::from_lines(&formatted_code, &formatted_preview)
|
||||
.unified_diff()
|
||||
.header("Stable", "Preview")
|
||||
)
|
||||
|
@ -242,6 +272,66 @@ fn format() {
|
|||
);
|
||||
}
|
||||
|
||||
fn format_file(source: &str, options: &PyFormatOptions, input_path: &Path) -> String {
|
||||
let (unformatted, formatted_code) = if source.contains("<RANGE_START>") {
|
||||
let mut content = source.to_string();
|
||||
let without_markers = content
|
||||
.replace("<RANGE_START>", "")
|
||||
.replace("<RANGE_END>", "");
|
||||
|
||||
while let Some(range_start_marker) = content.find("<RANGE_START>") {
|
||||
// Remove the start marker
|
||||
content.replace_range(
|
||||
range_start_marker..range_start_marker + "<RANGE_START>".len(),
|
||||
"",
|
||||
);
|
||||
|
||||
let range_end_marker = content[range_start_marker..]
|
||||
.find("<RANGE_END>")
|
||||
.expect("Matching <RANGE_END> marker for <RANGE_START> to exist")
|
||||
+ range_start_marker;
|
||||
|
||||
content.replace_range(range_end_marker..range_end_marker + "<RANGE_END>".len(), "");
|
||||
|
||||
// Replace all other markers to get a valid Python input
|
||||
let format_input = content
|
||||
.replace("<RANGE_START>", "")
|
||||
.replace("<RANGE_END>", "");
|
||||
|
||||
let range = TextRange::new(
|
||||
TextSize::try_from(range_start_marker).unwrap(),
|
||||
TextSize::try_from(range_end_marker).unwrap(),
|
||||
);
|
||||
|
||||
let formatted =
|
||||
format_range(&format_input, range, options.clone()).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Range-formatting of {} to succeed but encountered error {err}",
|
||||
input_path.display()
|
||||
)
|
||||
});
|
||||
|
||||
content.replace_range(
|
||||
Range::<usize>::from(formatted.source_range()),
|
||||
formatted.as_code(),
|
||||
);
|
||||
}
|
||||
|
||||
(Cow::Owned(without_markers), content)
|
||||
} else {
|
||||
let printed = format_module_source(source, options.clone()).expect("Formatting to succeed");
|
||||
let formatted_code = printed.into_code();
|
||||
|
||||
ensure_stability_when_formatting_twice(&formatted_code, options, input_path);
|
||||
|
||||
(Cow::Borrowed(source), formatted_code)
|
||||
};
|
||||
|
||||
ensure_unchanged_ast(&unformatted, &formatted_code, options, input_path);
|
||||
|
||||
formatted_code
|
||||
}
|
||||
|
||||
/// Format another time and make sure that there are no changes anymore
|
||||
fn ensure_stability_when_formatting_twice(
|
||||
formatted_code: &str,
|
||||
|
|
|
@ -1,319 +0,0 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/line_ranges_basic.py
|
||||
---
|
||||
## Input
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=5-6
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
def foo1(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
|
||||
def foo2(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
|
||||
def foo3(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
|
||||
def foo4(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
|
||||
|
||||
# Adding some unformated code covering a wide range of syntaxes.
|
||||
|
||||
if True:
|
||||
# Incorrectly indented prefix comments.
|
||||
pass
|
||||
|
||||
import typing
|
||||
from typing import (
|
||||
Any ,
|
||||
)
|
||||
class MyClass( object): # Trailing comment with extra leading space.
|
||||
#NOTE: The following indentation is incorrect:
|
||||
@decor( 1 * 3 )
|
||||
def my_func( arg):
|
||||
pass
|
||||
|
||||
try: # Trailing comment with extra leading space.
|
||||
for i in range(10): # Trailing comment with extra leading space.
|
||||
while condition:
|
||||
if something:
|
||||
then_something( )
|
||||
elif something_else:
|
||||
then_something_else( )
|
||||
except ValueError as e:
|
||||
unformatted( )
|
||||
finally:
|
||||
unformatted( )
|
||||
|
||||
async def test_async_unformatted( ): # Trailing comment with extra leading space.
|
||||
async for i in some_iter( unformatted ): # Trailing comment with extra leading space.
|
||||
await asyncio.sleep( 1 )
|
||||
async with some_context( unformatted ):
|
||||
print( "unformatted" )
|
||||
```
|
||||
|
||||
## Black Differences
|
||||
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,7 +1,18 @@
|
||||
# flags: --line-ranges=5-6
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
-def foo1(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
|
||||
+def foo1(
|
||||
+ parameter_1,
|
||||
+ parameter_2,
|
||||
+ parameter_3,
|
||||
+ parameter_4,
|
||||
+ parameter_5,
|
||||
+ parameter_6,
|
||||
+ parameter_7,
|
||||
+):
|
||||
+ pass
|
||||
+
|
||||
+
|
||||
def foo2(
|
||||
parameter_1,
|
||||
parameter_2,
|
||||
@@ -26,38 +37,52 @@
|
||||
pass
|
||||
|
||||
|
||||
-def foo4(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
|
||||
+def foo4(
|
||||
+ parameter_1,
|
||||
+ parameter_2,
|
||||
+ parameter_3,
|
||||
+ parameter_4,
|
||||
+ parameter_5,
|
||||
+ parameter_6,
|
||||
+ parameter_7,
|
||||
+):
|
||||
+ pass
|
||||
+
|
||||
|
||||
# Adding some unformated code covering a wide range of syntaxes.
|
||||
|
||||
if True:
|
||||
- # Incorrectly indented prefix comments.
|
||||
- pass
|
||||
+ # Incorrectly indented prefix comments.
|
||||
+ pass
|
||||
|
||||
-import typing
|
||||
-from typing import (
|
||||
- Any ,
|
||||
- )
|
||||
-class MyClass( object): # Trailing comment with extra leading space.
|
||||
- #NOTE: The following indentation is incorrect:
|
||||
- @decor( 1 * 3 )
|
||||
- def my_func( arg):
|
||||
- pass
|
||||
+import typing
|
||||
+from typing import (
|
||||
+ Any,
|
||||
+)
|
||||
+
|
||||
+
|
||||
+class MyClass(object): # Trailing comment with extra leading space.
|
||||
+ # NOTE: The following indentation is incorrect:
|
||||
+ @decor(1 * 3)
|
||||
+ def my_func(arg):
|
||||
+ pass
|
||||
|
||||
-try: # Trailing comment with extra leading space.
|
||||
- for i in range(10): # Trailing comment with extra leading space.
|
||||
- while condition:
|
||||
- if something:
|
||||
- then_something( )
|
||||
- elif something_else:
|
||||
- then_something_else( )
|
||||
-except ValueError as e:
|
||||
- unformatted( )
|
||||
+
|
||||
+try: # Trailing comment with extra leading space.
|
||||
+ for i in range(10): # Trailing comment with extra leading space.
|
||||
+ while condition:
|
||||
+ if something:
|
||||
+ then_something()
|
||||
+ elif something_else:
|
||||
+ then_something_else()
|
||||
+except ValueError as e:
|
||||
+ unformatted()
|
||||
finally:
|
||||
- unformatted( )
|
||||
+ unformatted()
|
||||
+
|
||||
|
||||
-async def test_async_unformatted( ): # Trailing comment with extra leading space.
|
||||
- async for i in some_iter( unformatted ): # Trailing comment with extra leading space.
|
||||
- await asyncio.sleep( 1 )
|
||||
- async with some_context( unformatted ):
|
||||
- print( "unformatted" )
|
||||
+async def test_async_unformatted(): # Trailing comment with extra leading space.
|
||||
+ async for i in some_iter(unformatted): # Trailing comment with extra leading space.
|
||||
+ await asyncio.sleep(1)
|
||||
+ async with some_context(unformatted):
|
||||
+ print("unformatted")
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=5-6
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
def foo1(
|
||||
parameter_1,
|
||||
parameter_2,
|
||||
parameter_3,
|
||||
parameter_4,
|
||||
parameter_5,
|
||||
parameter_6,
|
||||
parameter_7,
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
def foo2(
|
||||
parameter_1,
|
||||
parameter_2,
|
||||
parameter_3,
|
||||
parameter_4,
|
||||
parameter_5,
|
||||
parameter_6,
|
||||
parameter_7,
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
def foo3(
|
||||
parameter_1,
|
||||
parameter_2,
|
||||
parameter_3,
|
||||
parameter_4,
|
||||
parameter_5,
|
||||
parameter_6,
|
||||
parameter_7,
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
def foo4(
|
||||
parameter_1,
|
||||
parameter_2,
|
||||
parameter_3,
|
||||
parameter_4,
|
||||
parameter_5,
|
||||
parameter_6,
|
||||
parameter_7,
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
# Adding some unformated code covering a wide range of syntaxes.
|
||||
|
||||
if True:
|
||||
# Incorrectly indented prefix comments.
|
||||
pass
|
||||
|
||||
import typing
|
||||
from typing import (
|
||||
Any,
|
||||
)
|
||||
|
||||
|
||||
class MyClass(object): # Trailing comment with extra leading space.
|
||||
# NOTE: The following indentation is incorrect:
|
||||
@decor(1 * 3)
|
||||
def my_func(arg):
|
||||
pass
|
||||
|
||||
|
||||
try: # Trailing comment with extra leading space.
|
||||
for i in range(10): # Trailing comment with extra leading space.
|
||||
while condition:
|
||||
if something:
|
||||
then_something()
|
||||
elif something_else:
|
||||
then_something_else()
|
||||
except ValueError as e:
|
||||
unformatted()
|
||||
finally:
|
||||
unformatted()
|
||||
|
||||
|
||||
async def test_async_unformatted(): # Trailing comment with extra leading space.
|
||||
async for i in some_iter(unformatted): # Trailing comment with extra leading space.
|
||||
await asyncio.sleep(1)
|
||||
async with some_context(unformatted):
|
||||
print("unformatted")
|
||||
```
|
||||
|
||||
## Black Output
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=5-6
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
def foo1(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
|
||||
def foo2(
|
||||
parameter_1,
|
||||
parameter_2,
|
||||
parameter_3,
|
||||
parameter_4,
|
||||
parameter_5,
|
||||
parameter_6,
|
||||
parameter_7,
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
def foo3(
|
||||
parameter_1,
|
||||
parameter_2,
|
||||
parameter_3,
|
||||
parameter_4,
|
||||
parameter_5,
|
||||
parameter_6,
|
||||
parameter_7,
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
def foo4(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
|
||||
|
||||
# Adding some unformated code covering a wide range of syntaxes.
|
||||
|
||||
if True:
|
||||
# Incorrectly indented prefix comments.
|
||||
pass
|
||||
|
||||
import typing
|
||||
from typing import (
|
||||
Any ,
|
||||
)
|
||||
class MyClass( object): # Trailing comment with extra leading space.
|
||||
#NOTE: The following indentation is incorrect:
|
||||
@decor( 1 * 3 )
|
||||
def my_func( arg):
|
||||
pass
|
||||
|
||||
try: # Trailing comment with extra leading space.
|
||||
for i in range(10): # Trailing comment with extra leading space.
|
||||
while condition:
|
||||
if something:
|
||||
then_something( )
|
||||
elif something_else:
|
||||
then_something_else( )
|
||||
except ValueError as e:
|
||||
unformatted( )
|
||||
finally:
|
||||
unformatted( )
|
||||
|
||||
async def test_async_unformatted( ): # Trailing comment with extra leading space.
|
||||
async for i in some_iter( unformatted ): # Trailing comment with extra leading space.
|
||||
await asyncio.sleep( 1 )
|
||||
async with some_context( unformatted ):
|
||||
print( "unformatted" )
|
||||
```
|
||||
|
||||
|
|
@ -25,16 +25,14 @@ print ( "format me" )
|
|||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -6,7 +6,8 @@
|
||||
# This can be fixed in the future if we use a better diffing algorithm, or make Black
|
||||
# perform formatting in a single pass.
|
||||
|
||||
-print ( "format me" )
|
||||
@@ -9,5 +9,5 @@
|
||||
print ( "format me" )
|
||||
print("format me")
|
||||
print("format me")
|
||||
print("format me")
|
||||
print("format me")
|
||||
+print("format me")
|
||||
-print("format me")
|
||||
-print("format me")
|
||||
+print ( "format me" )
|
||||
+print ( "format me" )
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
|
@ -48,11 +46,11 @@ print ( "format me" )
|
|||
# This can be fixed in the future if we use a better diffing algorithm, or make Black
|
||||
# perform formatting in a single pass.
|
||||
|
||||
print ( "format me" )
|
||||
print("format me")
|
||||
print("format me")
|
||||
print("format me")
|
||||
print("format me")
|
||||
print("format me")
|
||||
print ( "format me" )
|
||||
print ( "format me" )
|
||||
```
|
||||
|
||||
## Black Output
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/line_ranges_fmt_off.py
|
||||
---
|
||||
## Input
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=7-7 --line-ranges=17-23
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
|
||||
# fmt: off
|
||||
import os
|
||||
def myfunc( ): # Intentionally unformatted.
|
||||
pass
|
||||
# fmt: on
|
||||
|
||||
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
# fmt: off
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
# fmt: on
|
||||
|
||||
|
||||
def myfunc( ): # This will be reformatted.
|
||||
print( {"this will be reformatted"} )
|
||||
```
|
||||
|
||||
## Black Differences
|
||||
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -9,8 +9,10 @@
|
||||
# fmt: on
|
||||
|
||||
|
||||
-def myfunc( ): # This will not be reformatted.
|
||||
- print( {"also won't be reformatted"} )
|
||||
+def myfunc(): # This will not be reformatted.
|
||||
+ print({"also won't be reformatted"})
|
||||
+
|
||||
+
|
||||
# fmt: off
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=7-7 --line-ranges=17-23
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
|
||||
# fmt: off
|
||||
import os
|
||||
def myfunc( ): # Intentionally unformatted.
|
||||
pass
|
||||
# fmt: on
|
||||
|
||||
|
||||
def myfunc(): # This will not be reformatted.
|
||||
print({"also won't be reformatted"})
|
||||
|
||||
|
||||
# fmt: off
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
# fmt: on
|
||||
|
||||
|
||||
def myfunc(): # This will be reformatted.
|
||||
print({"this will be reformatted"})
|
||||
```
|
||||
|
||||
## Black Output
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=7-7 --line-ranges=17-23
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
|
||||
# fmt: off
|
||||
import os
|
||||
def myfunc( ): # Intentionally unformatted.
|
||||
pass
|
||||
# fmt: on
|
||||
|
||||
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
# fmt: off
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
# fmt: on
|
||||
|
||||
|
||||
def myfunc(): # This will be reformatted.
|
||||
print({"this will be reformatted"})
|
||||
```
|
||||
|
||||
|
|
@ -33,12 +33,7 @@ class MyClass:
|
|||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -4,12 +4,11 @@
|
||||
|
||||
# Regression test for an edge case involving decorators and fmt: off/on.
|
||||
class MyClass:
|
||||
-
|
||||
# fmt: off
|
||||
@@ -9,7 +9,7 @@
|
||||
@decorator ( )
|
||||
# fmt: on
|
||||
def method():
|
||||
|
@ -47,7 +42,7 @@ class MyClass:
|
|||
|
||||
@decor(
|
||||
a=1,
|
||||
@@ -18,4 +17,4 @@
|
||||
@@ -18,4 +18,4 @@
|
||||
# fmt: on
|
||||
)
|
||||
def func():
|
||||
|
@ -64,6 +59,7 @@ class MyClass:
|
|||
|
||||
# Regression test for an edge case involving decorators and fmt: off/on.
|
||||
class MyClass:
|
||||
|
||||
# fmt: off
|
||||
@decorator ( )
|
||||
# fmt: on
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/line_ranges_fmt_off_overlap.py
|
||||
---
|
||||
## Input
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=11-17
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
|
||||
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
# fmt: off
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
# fmt: on
|
||||
|
||||
|
||||
def myfunc( ): # This will be reformatted.
|
||||
print( {"this will be reformatted"} )
|
||||
```
|
||||
|
||||
## Black Differences
|
||||
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -3,8 +3,10 @@
|
||||
# flag above as it's formatting specifically these lines.
|
||||
|
||||
|
||||
-def myfunc( ): # This will not be reformatted.
|
||||
- print( {"also won't be reformatted"} )
|
||||
+def myfunc(): # This will not be reformatted.
|
||||
+ print({"also won't be reformatted"})
|
||||
+
|
||||
+
|
||||
# fmt: off
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=11-17
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
|
||||
|
||||
def myfunc(): # This will not be reformatted.
|
||||
print({"also won't be reformatted"})
|
||||
|
||||
|
||||
# fmt: off
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
# fmt: on
|
||||
|
||||
|
||||
def myfunc(): # This will be reformatted.
|
||||
print({"this will be reformatted"})
|
||||
```
|
||||
|
||||
## Black Output
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=11-17
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
|
||||
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
# fmt: off
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
def myfunc( ): # This will not be reformatted.
|
||||
print( {"also won't be reformatted"} )
|
||||
# fmt: on
|
||||
|
||||
|
||||
def myfunc(): # This will be reformatted.
|
||||
print({"this will be reformatted"})
|
||||
```
|
||||
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/line_ranges_indentation.py
|
||||
---
|
||||
## Input
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=5-5
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
if cond1:
|
||||
print("first")
|
||||
if cond2:
|
||||
print("second")
|
||||
else:
|
||||
print("else")
|
||||
|
||||
if another_cond:
|
||||
print("will not be changed")
|
||||
```
|
||||
|
||||
## Black Differences
|
||||
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -9,4 +9,4 @@
|
||||
print("else")
|
||||
|
||||
if another_cond:
|
||||
- print("will not be changed")
|
||||
+ print("will not be changed")
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=5-5
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
if cond1:
|
||||
print("first")
|
||||
if cond2:
|
||||
print("second")
|
||||
else:
|
||||
print("else")
|
||||
|
||||
if another_cond:
|
||||
print("will not be changed")
|
||||
```
|
||||
|
||||
## Black Output
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=5-5
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
if cond1:
|
||||
print("first")
|
||||
if cond2:
|
||||
print("second")
|
||||
else:
|
||||
print("else")
|
||||
|
||||
if another_cond:
|
||||
print("will not be changed")
|
||||
```
|
||||
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/line_ranges_two_passes.py
|
||||
---
|
||||
## Input
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=9-11
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
|
||||
# This is a specific case for Black's two-pass formatting behavior in `format_str`.
|
||||
# The second pass must respect the line ranges before the first pass.
|
||||
|
||||
|
||||
def restrict_to_this_line(arg1,
|
||||
arg2,
|
||||
arg3):
|
||||
print ( "This should not be formatted." )
|
||||
print ( "Note that in the second pass, the original line range 9-11 will cover these print lines.")
|
||||
```
|
||||
|
||||
## Black Differences
|
||||
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -7,5 +7,7 @@
|
||||
|
||||
|
||||
def restrict_to_this_line(arg1, arg2, arg3):
|
||||
- print ( "This should not be formatted." )
|
||||
- print ( "Note that in the second pass, the original line range 9-11 will cover these print lines.")
|
||||
+ print("This should not be formatted.")
|
||||
+ print(
|
||||
+ "Note that in the second pass, the original line range 9-11 will cover these print lines."
|
||||
+ )
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=9-11
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
|
||||
# This is a specific case for Black's two-pass formatting behavior in `format_str`.
|
||||
# The second pass must respect the line ranges before the first pass.
|
||||
|
||||
|
||||
def restrict_to_this_line(arg1, arg2, arg3):
|
||||
print("This should not be formatted.")
|
||||
print(
|
||||
"Note that in the second pass, the original line range 9-11 will cover these print lines."
|
||||
)
|
||||
```
|
||||
|
||||
## Black Output
|
||||
|
||||
```python
|
||||
# flags: --line-ranges=9-11
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
|
||||
# This is a specific case for Black's two-pass formatting behavior in `format_str`.
|
||||
# The second pass must respect the line ranges before the first pass.
|
||||
|
||||
|
||||
def restrict_to_this_line(arg1, arg2, arg3):
|
||||
print ( "This should not be formatted." )
|
||||
print ( "Note that in the second pass, the original line range 9-11 will cover these print lines.")
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/ancestory.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
def test ():
|
||||
if True:
|
||||
print(<RANGE_START>1 + 2)
|
||||
|
||||
else:
|
||||
print(3 + 4)<RANGE_END>
|
||||
|
||||
print(" Do not format this")
|
||||
|
||||
|
||||
|
||||
def test_empty_lines ():
|
||||
if True:
|
||||
print(<RANGE_START>1 + 2)
|
||||
|
||||
|
||||
else:
|
||||
print(3 + 4)<RANGE_END>
|
||||
|
||||
print(" Do not format this")
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
def test ():
|
||||
if True:
|
||||
print(1 + 2)
|
||||
|
||||
else:
|
||||
print(3 + 4)
|
||||
|
||||
print(" Do not format this")
|
||||
|
||||
|
||||
|
||||
def test_empty_lines ():
|
||||
if True:
|
||||
print(1 + 2)
|
||||
|
||||
else:
|
||||
print(3 + 4)
|
||||
|
||||
print(" Do not format this")
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/clause_header.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
def test(<RANGE_START>a, b, c: str<RANGE_END>, d):
|
||||
print ( "Don't format the body when only making changes to the clause header")
|
||||
|
||||
|
||||
print( "Should not get formatted")
|
||||
|
||||
|
||||
class <RANGE_START> Test(OtherClass<RANGE_END>)\
|
||||
: # comment
|
||||
|
||||
# Should not get formatted
|
||||
def __init__( self):
|
||||
print("hello")
|
||||
|
||||
print( "dont' format this")
|
||||
|
||||
|
||||
def test2(<RANGE_START>a, b, c: str, d):<RANGE_END>
|
||||
print ( "Don't format the body when only making changes to the clause header")
|
||||
|
||||
|
||||
print( "Should not get formatted")
|
||||
|
||||
|
||||
def test3(<RANGE_START>a, b, c: str, d):<RANGE_END> # fmt: skip
|
||||
print ( "Don't format the body when only making changes to the clause header")
|
||||
|
||||
|
||||
|
||||
def test4(<RANGE_START> a):
|
||||
print("Format this" )
|
||||
|
||||
if True:
|
||||
print( "and this")<RANGE_END>
|
||||
|
||||
print("Not this" )
|
||||
|
||||
|
||||
<RANGE_START>if a + b : # trailing clause header comment<RANGE_END>
|
||||
print("Not formatted" )
|
||||
|
||||
|
||||
<RANGE_START>if b + c :<RANGE_END> # trailing clause header comment
|
||||
print("Not formatted" )
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
def test(a, b, c: str, d):
|
||||
print ( "Don't format the body when only making changes to the clause header")
|
||||
|
||||
|
||||
print( "Should not get formatted")
|
||||
|
||||
|
||||
class Test(OtherClass): # comment
|
||||
|
||||
# Should not get formatted
|
||||
def __init__( self):
|
||||
print("hello")
|
||||
|
||||
print( "dont' format this")
|
||||
|
||||
|
||||
def test2(a, b, c: str, d):
|
||||
print ( "Don't format the body when only making changes to the clause header")
|
||||
|
||||
|
||||
print( "Should not get formatted")
|
||||
|
||||
|
||||
def test3(a, b, c: str, d): # fmt: skip
|
||||
print ( "Don't format the body when only making changes to the clause header")
|
||||
|
||||
|
||||
|
||||
def test4(a):
|
||||
print("Format this")
|
||||
|
||||
if True:
|
||||
print("and this")
|
||||
|
||||
print("Not this" )
|
||||
|
||||
|
||||
if a + b: # trailing clause header comment
|
||||
print("Not formatted" )
|
||||
|
||||
|
||||
if b + c: # trailing clause header comment
|
||||
print("Not formatted" )
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/comment_only_range.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
def test ():
|
||||
<RANGE_START># Some leading comment
|
||||
# that spans multiple lines
|
||||
<RANGE_END>
|
||||
print("Do not format this" )
|
||||
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
def test ():
|
||||
# Some leading comment
|
||||
# that spans multiple lines
|
||||
|
||||
print("Do not format this" )
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/decorators.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
def test():
|
||||
|
||||
print("before" )
|
||||
|
||||
@<RANGE_START> decorator( aa)
|
||||
|
||||
<RANGE_END>def func ():
|
||||
print("Do not format this" )
|
||||
|
||||
|
||||
<RANGE_START>@ decorator( a)
|
||||
def test( a):<RANGE_END>
|
||||
print( "body")
|
||||
|
||||
print("after" )
|
||||
|
||||
|
||||
<RANGE_START>@ decorator( a)<RANGE_END>
|
||||
def test( a):
|
||||
print( "body")
|
||||
|
||||
print("after" )
|
||||
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
def test():
|
||||
|
||||
print("before" )
|
||||
|
||||
@decorator(aa)
|
||||
def func():
|
||||
print("Do not format this" )
|
||||
|
||||
|
||||
@decorator(a)
|
||||
def test(a):
|
||||
print( "body")
|
||||
|
||||
print("after" )
|
||||
|
||||
|
||||
@decorator(a)
|
||||
def test( a):
|
||||
print( "body")
|
||||
|
||||
print("after" )
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,391 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/docstring_code_examples.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
def doctest_simple ():
|
||||
<RANGE_START>"""
|
||||
Do cool stuff.
|
||||
|
||||
>>> cool_stuff( 1 )
|
||||
2
|
||||
"""
|
||||
pass<RANGE_END>
|
||||
|
||||
|
||||
def doctest_only ():
|
||||
<RANGE_START>"""
|
||||
Do cool stuff.
|
||||
|
||||
>>> def cool_stuff( x ):
|
||||
... print( f"hi {x}" );
|
||||
hi 2
|
||||
"""<RANGE_END>
|
||||
pass
|
||||
|
||||
|
||||
def in_doctest ():
|
||||
"""
|
||||
Do cool stuff.
|
||||
<RANGE_START>
|
||||
>>> cool_stuff( x )
|
||||
>>> cool_stuff( y )
|
||||
2<RANGE_END>
|
||||
"""
|
||||
pass
|
||||
|
||||
def suppressed_doctest ():
|
||||
"""
|
||||
Do cool stuff.
|
||||
<RANGE_START>
|
||||
>>> cool_stuff( x )
|
||||
>>> cool_stuff( y )
|
||||
2<RANGE_END>
|
||||
""" # fmt: skip
|
||||
pass
|
||||
|
||||
|
||||
def fmt_off_doctest ():
|
||||
# fmt: off
|
||||
"""
|
||||
Do cool stuff.
|
||||
<RANGE_START>
|
||||
>>> cool_stuff( x )
|
||||
>>> cool_stuff( y )
|
||||
2<RANGE_END>
|
||||
"""
|
||||
# fmt: on
|
||||
pass
|
||||
|
||||
|
||||
|
||||
if True:
|
||||
def doctest_long_lines():
|
||||
<RANGE_START>
|
||||
'''
|
||||
This won't get wrapped even though it exceeds our configured
|
||||
line width because it doesn't exceed the line width within this
|
||||
docstring. e.g, the `f` in `foo` is treated as the first column.
|
||||
>>> foo, bar, quux = this_is_a_long_line(lion, giraffe, hippo, zeba, lemur, penguin, monkey)
|
||||
|
||||
But this one is long enough to get wrapped.
|
||||
>>> foo, bar, quux = this_is_a_long_line(lion, giraffe, hippo, zeba, lemur, penguin, monkey, spider, bear, leopard)
|
||||
|
||||
This one doesn't get wrapped with an indent width of 4 even with `dynamic` line width
|
||||
>>> a = this_is_a_long_line(lion, giraffe, hippo, zebra, lemur, penguin, monkey)
|
||||
|
||||
This one gets wrapped with `dynamic` line width and an indent width of 4 because it exceeds the width by 1
|
||||
>>> ab = this_is_a_long_line(lion, giraffe, hippo, zebra, lemur, penguin, monkey)
|
||||
'''
|
||||
# This demonstrates a normal line that will get wrapped but won't
|
||||
# get wrapped in the docstring above because of how the line-width
|
||||
# setting gets reset at the first column in each code snippet.
|
||||
foo, bar, quux = this_is_a_long_line(lion, giraffe, hippo, zeba, lemur, penguin, monkey)
|
||||
<RANGE_END>
|
||||
|
||||
|
||||
if True:
|
||||
def doctest_long_lines():
|
||||
<RANGE_START>'''
|
||||
This won't get wrapped even though it exceeds our configured
|
||||
line width because it doesn't exceed the line width within this
|
||||
docstring. e.g, the `f` in `foo` is treated as the first column.
|
||||
>>> foo, bar, quux = this_is_a_long_line(lion, giraffe, hippo, zeba, lemur, penguin, monkey)
|
||||
|
||||
But this one is long enough to get wrapped.
|
||||
>>> foo, bar, quux = this_is_a_long_line(lion, giraffe, hippo, zeba, lemur, penguin, monkey, spider, bear, leopard)
|
||||
|
||||
This one doesn't get wrapped with an indent width of 4 even with `dynamic` line width
|
||||
>>> a = this_is_a_long_line(lion, giraffe, hippo, zebra, lemur, penguin, monkey)
|
||||
|
||||
This one gets wrapped with `dynamic` line width and an indent width of 4 because it exceeds the width by 1
|
||||
>>> ab = this_is_a_long_line(lion, giraffe, hippo, zebra, lemur, penguin, monkey)
|
||||
'''<RANGE_END>
|
||||
# This demonstrates a normal line that will get wrapped but won't
|
||||
# get wrapped in the docstring above because of how the line-width
|
||||
# setting gets reset at the first column in each code snippet.
|
||||
foo, bar, quux = this_is_a_long_line(lion, giraffe, hippo, zeba, lemur, penguin, monkey)
|
||||
|
||||
```
|
||||
|
||||
## Outputs
|
||||
### Output 1
|
||||
```
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
line-ending = LineFeed
|
||||
magic-trailing-comma = Respect
|
||||
docstring-code = Enabled
|
||||
docstring-code-line-width = "dynamic"
|
||||
preview = Disabled
|
||||
target_version = Py38
|
||||
source_type = Python
|
||||
```
|
||||
|
||||
```python
|
||||
def doctest_simple ():
|
||||
"""
|
||||
Do cool stuff.
|
||||
|
||||
>>> cool_stuff(1)
|
||||
2
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def doctest_only ():
|
||||
"""
|
||||
Do cool stuff.
|
||||
|
||||
>>> def cool_stuff(x):
|
||||
... print(f"hi {x}")
|
||||
hi 2
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def in_doctest ():
|
||||
"""
|
||||
Do cool stuff.
|
||||
|
||||
>>> cool_stuff(x)
|
||||
>>> cool_stuff(y)
|
||||
2
|
||||
"""
|
||||
pass
|
||||
|
||||
def suppressed_doctest ():
|
||||
"""
|
||||
Do cool stuff.
|
||||
|
||||
>>> cool_stuff( x )
|
||||
>>> cool_stuff( y )
|
||||
2
|
||||
""" # fmt: skip
|
||||
pass
|
||||
|
||||
|
||||
def fmt_off_doctest ():
|
||||
# fmt: off
|
||||
"""
|
||||
Do cool stuff.
|
||||
|
||||
>>> cool_stuff( x )
|
||||
>>> cool_stuff( y )
|
||||
2
|
||||
"""
|
||||
# fmt: on
|
||||
pass
|
||||
|
||||
|
||||
|
||||
if True:
|
||||
def doctest_long_lines():
|
||||
"""
|
||||
This won't get wrapped even though it exceeds our configured
|
||||
line width because it doesn't exceed the line width within this
|
||||
docstring. e.g, the `f` in `foo` is treated as the first column.
|
||||
>>> foo, bar, quux = this_is_a_long_line(
|
||||
... lion, giraffe, hippo, zeba, lemur, penguin, monkey
|
||||
... )
|
||||
|
||||
But this one is long enough to get wrapped.
|
||||
>>> foo, bar, quux = this_is_a_long_line(
|
||||
... lion,
|
||||
... giraffe,
|
||||
... hippo,
|
||||
... zeba,
|
||||
... lemur,
|
||||
... penguin,
|
||||
... monkey,
|
||||
... spider,
|
||||
... bear,
|
||||
... leopard,
|
||||
... )
|
||||
|
||||
This one doesn't get wrapped with an indent width of 4 even with `dynamic` line width
|
||||
>>> a = this_is_a_long_line(lion, giraffe, hippo, zebra, lemur, penguin, monkey)
|
||||
|
||||
This one gets wrapped with `dynamic` line width and an indent width of 4 because it exceeds the width by 1
|
||||
>>> ab = this_is_a_long_line(
|
||||
... lion, giraffe, hippo, zebra, lemur, penguin, monkey
|
||||
... )
|
||||
"""
|
||||
# This demonstrates a normal line that will get wrapped but won't
|
||||
# get wrapped in the docstring above because of how the line-width
|
||||
# setting gets reset at the first column in each code snippet.
|
||||
foo, bar, quux = this_is_a_long_line(
|
||||
lion, giraffe, hippo, zeba, lemur, penguin, monkey
|
||||
)
|
||||
|
||||
|
||||
if True:
|
||||
def doctest_long_lines():
|
||||
"""
|
||||
This won't get wrapped even though it exceeds our configured
|
||||
line width because it doesn't exceed the line width within this
|
||||
docstring. e.g, the `f` in `foo` is treated as the first column.
|
||||
>>> foo, bar, quux = this_is_a_long_line(
|
||||
... lion, giraffe, hippo, zeba, lemur, penguin, monkey
|
||||
... )
|
||||
|
||||
But this one is long enough to get wrapped.
|
||||
>>> foo, bar, quux = this_is_a_long_line(
|
||||
... lion,
|
||||
... giraffe,
|
||||
... hippo,
|
||||
... zeba,
|
||||
... lemur,
|
||||
... penguin,
|
||||
... monkey,
|
||||
... spider,
|
||||
... bear,
|
||||
... leopard,
|
||||
... )
|
||||
|
||||
This one doesn't get wrapped with an indent width of 4 even with `dynamic` line width
|
||||
>>> a = this_is_a_long_line(lion, giraffe, hippo, zebra, lemur, penguin, monkey)
|
||||
|
||||
This one gets wrapped with `dynamic` line width and an indent width of 4 because it exceeds the width by 1
|
||||
>>> ab = this_is_a_long_line(
|
||||
... lion, giraffe, hippo, zebra, lemur, penguin, monkey
|
||||
... )
|
||||
"""
|
||||
# This demonstrates a normal line that will get wrapped but won't
|
||||
# get wrapped in the docstring above because of how the line-width
|
||||
# setting gets reset at the first column in each code snippet.
|
||||
foo, bar, quux = this_is_a_long_line(lion, giraffe, hippo, zeba, lemur, penguin, monkey)
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Output 2
|
||||
```
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
line-ending = LineFeed
|
||||
magic-trailing-comma = Respect
|
||||
docstring-code = Enabled
|
||||
docstring-code-line-width = 88
|
||||
preview = Disabled
|
||||
target_version = Py38
|
||||
source_type = Python
|
||||
```
|
||||
|
||||
```python
|
||||
def doctest_simple ():
|
||||
"""
|
||||
Do cool stuff.
|
||||
|
||||
>>> cool_stuff(1)
|
||||
2
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def doctest_only ():
|
||||
"""
|
||||
Do cool stuff.
|
||||
|
||||
>>> def cool_stuff(x):
|
||||
... print(f"hi {x}")
|
||||
hi 2
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def in_doctest ():
|
||||
"""
|
||||
Do cool stuff.
|
||||
|
||||
>>> cool_stuff(x)
|
||||
>>> cool_stuff(y)
|
||||
2
|
||||
"""
|
||||
pass
|
||||
|
||||
def suppressed_doctest ():
|
||||
"""
|
||||
Do cool stuff.
|
||||
|
||||
>>> cool_stuff( x )
|
||||
>>> cool_stuff( y )
|
||||
2
|
||||
""" # fmt: skip
|
||||
pass
|
||||
|
||||
|
||||
def fmt_off_doctest ():
|
||||
# fmt: off
|
||||
"""
|
||||
Do cool stuff.
|
||||
|
||||
>>> cool_stuff( x )
|
||||
>>> cool_stuff( y )
|
||||
2
|
||||
"""
|
||||
# fmt: on
|
||||
pass
|
||||
|
||||
|
||||
|
||||
if True:
|
||||
def doctest_long_lines():
|
||||
"""
|
||||
This won't get wrapped even though it exceeds our configured
|
||||
line width because it doesn't exceed the line width within this
|
||||
docstring. e.g, the `f` in `foo` is treated as the first column.
|
||||
>>> foo, bar, quux = this_is_a_long_line(lion, giraffe, hippo, zeba, lemur, penguin, monkey)
|
||||
|
||||
But this one is long enough to get wrapped.
|
||||
>>> foo, bar, quux = this_is_a_long_line(
|
||||
... lion, giraffe, hippo, zeba, lemur, penguin, monkey, spider, bear, leopard
|
||||
... )
|
||||
|
||||
This one doesn't get wrapped with an indent width of 4 even with `dynamic` line width
|
||||
>>> a = this_is_a_long_line(lion, giraffe, hippo, zebra, lemur, penguin, monkey)
|
||||
|
||||
This one gets wrapped with `dynamic` line width and an indent width of 4 because it exceeds the width by 1
|
||||
>>> ab = this_is_a_long_line(lion, giraffe, hippo, zebra, lemur, penguin, monkey)
|
||||
"""
|
||||
# This demonstrates a normal line that will get wrapped but won't
|
||||
# get wrapped in the docstring above because of how the line-width
|
||||
# setting gets reset at the first column in each code snippet.
|
||||
foo, bar, quux = this_is_a_long_line(
|
||||
lion, giraffe, hippo, zeba, lemur, penguin, monkey
|
||||
)
|
||||
|
||||
|
||||
if True:
|
||||
def doctest_long_lines():
|
||||
"""
|
||||
This won't get wrapped even though it exceeds our configured
|
||||
line width because it doesn't exceed the line width within this
|
||||
docstring. e.g, the `f` in `foo` is treated as the first column.
|
||||
>>> foo, bar, quux = this_is_a_long_line(lion, giraffe, hippo, zeba, lemur, penguin, monkey)
|
||||
|
||||
But this one is long enough to get wrapped.
|
||||
>>> foo, bar, quux = this_is_a_long_line(
|
||||
... lion, giraffe, hippo, zeba, lemur, penguin, monkey, spider, bear, leopard
|
||||
... )
|
||||
|
||||
This one doesn't get wrapped with an indent width of 4 even with `dynamic` line width
|
||||
>>> a = this_is_a_long_line(lion, giraffe, hippo, zebra, lemur, penguin, monkey)
|
||||
|
||||
This one gets wrapped with `dynamic` line width and an indent width of 4 because it exceeds the width by 1
|
||||
>>> ab = this_is_a_long_line(lion, giraffe, hippo, zebra, lemur, penguin, monkey)
|
||||
"""
|
||||
# This demonstrates a normal line that will get wrapped but won't
|
||||
# get wrapped in the docstring above because of how the line-width
|
||||
# setting gets reset at the first column in each code snippet.
|
||||
foo, bar, quux = this_is_a_long_line(lion, giraffe, hippo, zeba, lemur, penguin, monkey)
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/empty_file.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
<RANGE_START><RANGE_END>```
|
||||
|
||||
## Output
|
||||
```python
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/empty_range.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
def test():
|
||||
<RANGE_START><RANGE_END>print( "test" )
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
def test():
|
||||
print( "test" )
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/fmt_on_off.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
class MyClass:
|
||||
|
||||
# Range that falls entirely in a suppressed range
|
||||
# fmt: off<RANGE_START>
|
||||
def method( self ):
|
||||
print ( "str" )
|
||||
<RANGE_END># fmt: on
|
||||
|
||||
# This should net get formatted because it isn't in a formatting range.
|
||||
def not_in_formatting_range ( self): ...
|
||||
|
||||
|
||||
# Range that starts in a suppressed range and ends in a formatting range
|
||||
# fmt: off<RANGE_START>
|
||||
def other( self):
|
||||
print ( "str" )
|
||||
|
||||
# fmt: on
|
||||
|
||||
def formatted ( self):
|
||||
pass
|
||||
<RANGE_END>
|
||||
def outside_formatting_range (self): pass
|
||||
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
class MyClass:
|
||||
|
||||
# Range that falls entirely in a suppressed range
|
||||
# fmt: off
|
||||
def method( self ):
|
||||
print ( "str" )
|
||||
# fmt: on
|
||||
|
||||
# This should net get formatted because it isn't in a formatting range.
|
||||
def not_in_formatting_range ( self): ...
|
||||
|
||||
|
||||
# Range that starts in a suppressed range and ends in a formatting range
|
||||
# fmt: off
|
||||
def other( self):
|
||||
print ( "str" )
|
||||
|
||||
# fmt: on
|
||||
|
||||
def formatted(self):
|
||||
pass
|
||||
|
||||
def outside_formatting_range (self): pass
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,310 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/indent.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
# Formats the entire function with tab or 4 space indentation
|
||||
# because the statement indentations don't match the preferred indentation.
|
||||
def test ():
|
||||
print("before" )
|
||||
<RANGE_START>1 + 2
|
||||
if True:
|
||||
pass
|
||||
print("Done" )<RANGE_END>
|
||||
|
||||
print("formatted" )
|
||||
|
||||
print("not formatted" )
|
||||
|
||||
def test2 ():
|
||||
print("before" )
|
||||
<RANGE_START>1 + 2
|
||||
(
|
||||
3 + 2
|
||||
)
|
||||
print("Done" )<RANGE_END>
|
||||
|
||||
print("formatted" )
|
||||
|
||||
print("not formatted" )
|
||||
|
||||
def test3 ():
|
||||
print("before" )
|
||||
<RANGE_START>1 + 2
|
||||
"""A Multiline string
|
||||
that starts at the beginning of the line and we need to preserve the leading spaces"""
|
||||
|
||||
"""A Multiline string
|
||||
that has some indentation on the second line and we need to preserve the leading spaces"""
|
||||
|
||||
print("Done" )<RANGE_END>
|
||||
|
||||
|
||||
def test4 ():
|
||||
print("before" )
|
||||
<RANGE_START>1 + 2
|
||||
"""A Multiline string
|
||||
that uses the same indentation as the formatted code will. This should not be dedented."""
|
||||
|
||||
print("Done" )<RANGE_END>
|
||||
|
||||
def test5 ():
|
||||
print("before" )
|
||||
if True:
|
||||
print("Format to fix indentation" )
|
||||
print(<RANGE_START>1 + 2)
|
||||
|
||||
else:
|
||||
print(3 + 4)<RANGE_END>
|
||||
print("Format to fix indentation" )
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def test6 ():
|
||||
<RANGE_START>
|
||||
print("Format" )
|
||||
print(3 + 4)<RANGE_END>
|
||||
print("Format to fix indentation" )
|
||||
```
|
||||
|
||||
## Outputs
|
||||
### Output 1
|
||||
```
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
line-ending = LineFeed
|
||||
magic-trailing-comma = Respect
|
||||
docstring-code = Disabled
|
||||
docstring-code-line-width = "dynamic"
|
||||
preview = Disabled
|
||||
target_version = Py38
|
||||
source_type = Python
|
||||
```
|
||||
|
||||
```python
|
||||
# Formats the entire function with tab or 4 space indentation
|
||||
# because the statement indentations don't match the preferred indentation.
|
||||
def test ():
|
||||
print("before")
|
||||
1 + 2
|
||||
if True:
|
||||
pass
|
||||
print("Done")
|
||||
|
||||
print("formatted")
|
||||
|
||||
print("not formatted" )
|
||||
|
||||
def test2 ():
|
||||
print("before")
|
||||
1 + 2
|
||||
(3 + 2)
|
||||
print("Done")
|
||||
|
||||
print("formatted")
|
||||
|
||||
print("not formatted" )
|
||||
|
||||
def test3 ():
|
||||
print("before")
|
||||
1 + 2
|
||||
"""A Multiline string
|
||||
that starts at the beginning of the line and we need to preserve the leading spaces"""
|
||||
|
||||
"""A Multiline string
|
||||
that has some indentation on the second line and we need to preserve the leading spaces"""
|
||||
|
||||
print("Done")
|
||||
|
||||
|
||||
def test4 ():
|
||||
print("before")
|
||||
1 + 2
|
||||
"""A Multiline string
|
||||
that uses the same indentation as the formatted code will. This should not be dedented."""
|
||||
|
||||
print("Done")
|
||||
|
||||
def test5 ():
|
||||
print("before")
|
||||
if True:
|
||||
print("Format to fix indentation")
|
||||
print(1 + 2)
|
||||
|
||||
else:
|
||||
print(3 + 4)
|
||||
print("Format to fix indentation")
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def test6 ():
|
||||
print("Format")
|
||||
print(3 + 4)
|
||||
print("Format to fix indentation" )
|
||||
```
|
||||
|
||||
|
||||
### Output 2
|
||||
```
|
||||
indent-style = tab
|
||||
line-width = 88
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
line-ending = LineFeed
|
||||
magic-trailing-comma = Respect
|
||||
docstring-code = Disabled
|
||||
docstring-code-line-width = "dynamic"
|
||||
preview = Disabled
|
||||
target_version = Py38
|
||||
source_type = Python
|
||||
```
|
||||
|
||||
```python
|
||||
# Formats the entire function with tab or 4 space indentation
|
||||
# because the statement indentations don't match the preferred indentation.
|
||||
def test ():
|
||||
print("before")
|
||||
1 + 2
|
||||
if True:
|
||||
pass
|
||||
print("Done")
|
||||
|
||||
print("formatted")
|
||||
|
||||
print("not formatted" )
|
||||
|
||||
def test2 ():
|
||||
print("before")
|
||||
1 + 2
|
||||
(3 + 2)
|
||||
print("Done")
|
||||
|
||||
print("formatted")
|
||||
|
||||
print("not formatted" )
|
||||
|
||||
def test3 ():
|
||||
print("before")
|
||||
1 + 2
|
||||
"""A Multiline string
|
||||
that starts at the beginning of the line and we need to preserve the leading spaces"""
|
||||
|
||||
"""A Multiline string
|
||||
that has some indentation on the second line and we need to preserve the leading spaces"""
|
||||
|
||||
print("Done")
|
||||
|
||||
|
||||
def test4 ():
|
||||
print("before")
|
||||
1 + 2
|
||||
"""A Multiline string
|
||||
that uses the same indentation as the formatted code will. This should not be dedented."""
|
||||
|
||||
print("Done")
|
||||
|
||||
def test5 ():
|
||||
print("before")
|
||||
if True:
|
||||
print("Format to fix indentation")
|
||||
print(1 + 2)
|
||||
|
||||
else:
|
||||
print(3 + 4)
|
||||
print("Format to fix indentation")
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def test6 ():
|
||||
print("Format")
|
||||
print(3 + 4)
|
||||
print("Format to fix indentation")
|
||||
```
|
||||
|
||||
|
||||
### Output 3
|
||||
```
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
indent-width = 2
|
||||
quote-style = Double
|
||||
line-ending = LineFeed
|
||||
magic-trailing-comma = Respect
|
||||
docstring-code = Disabled
|
||||
docstring-code-line-width = "dynamic"
|
||||
preview = Disabled
|
||||
target_version = Py38
|
||||
source_type = Python
|
||||
```
|
||||
|
||||
```python
|
||||
# Formats the entire function with tab or 4 space indentation
|
||||
# because the statement indentations don't match the preferred indentation.
|
||||
def test ():
|
||||
print("before" )
|
||||
1 + 2
|
||||
if True:
|
||||
pass
|
||||
print("Done")
|
||||
|
||||
print("formatted" )
|
||||
|
||||
print("not formatted" )
|
||||
|
||||
def test2 ():
|
||||
print("before" )
|
||||
1 + 2
|
||||
(3 + 2)
|
||||
print("Done")
|
||||
|
||||
print("formatted" )
|
||||
|
||||
print("not formatted" )
|
||||
|
||||
def test3 ():
|
||||
print("before" )
|
||||
1 + 2
|
||||
"""A Multiline string
|
||||
that starts at the beginning of the line and we need to preserve the leading spaces"""
|
||||
|
||||
"""A Multiline string
|
||||
that has some indentation on the second line and we need to preserve the leading spaces"""
|
||||
|
||||
print("Done")
|
||||
|
||||
|
||||
def test4 ():
|
||||
print("before" )
|
||||
1 + 2
|
||||
"""A Multiline string
|
||||
that uses the same indentation as the formatted code will. This should not be dedented."""
|
||||
|
||||
print("Done")
|
||||
|
||||
def test5 ():
|
||||
print("before" )
|
||||
if True:
|
||||
print("Format to fix indentation")
|
||||
print(1 + 2)
|
||||
|
||||
else:
|
||||
print(3 + 4)
|
||||
print("Format to fix indentation")
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def test6 ():
|
||||
print("Format")
|
||||
print(3 + 4)
|
||||
print("Format to fix indentation")
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/leading_comments.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
def test ():
|
||||
print( "hello" )
|
||||
<RANGE_START># leading comment
|
||||
1 + 2
|
||||
|
||||
print( "world" )<RANGE_END>
|
||||
|
||||
print( "unformatted" )
|
||||
|
||||
|
||||
print( "Hy" )
|
||||
|
||||
|
||||
def test2 ():
|
||||
print( "hello" )
|
||||
# Leading comments don't get formatted. That's why Ruff won't fixup
|
||||
# the indentation here. That's something we might want to explore in the future
|
||||
# leading comment 1<RANGE_START>
|
||||
# leading comment 2
|
||||
1 + 2
|
||||
|
||||
print( "world" )<RANGE_END>
|
||||
|
||||
print( "unformatted" )
|
||||
|
||||
def test3 ():
|
||||
<RANGE_START>print( "hello" )
|
||||
# leading comment 1
|
||||
# leading comment 2
|
||||
1 + 2
|
||||
|
||||
print( "world" )<RANGE_END>
|
||||
|
||||
print( "unformatted" )
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
def test ():
|
||||
print( "hello" )
|
||||
# leading comment
|
||||
1 + 2
|
||||
|
||||
print("world")
|
||||
|
||||
print( "unformatted" )
|
||||
|
||||
|
||||
print( "Hy" )
|
||||
|
||||
|
||||
def test2 ():
|
||||
print( "hello" )
|
||||
# Leading comments don't get formatted. That's why Ruff won't fixup
|
||||
# the indentation here. That's something we might want to explore in the future
|
||||
# leading comment 1
|
||||
# leading comment 2
|
||||
1 + 2
|
||||
|
||||
print("world")
|
||||
|
||||
print( "unformatted" )
|
||||
|
||||
def test3 ():
|
||||
print("hello")
|
||||
# leading comment 1
|
||||
# leading comment 2
|
||||
1 + 2
|
||||
|
||||
print("world")
|
||||
|
||||
print( "unformatted" )
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/leading_trailing_comments.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
def test ():
|
||||
# Leading comments before the statements that should be formatted
|
||||
# Don't duplicate the comments
|
||||
<RANGE_START>print( "format this")<RANGE_END> # trailing end of line comment
|
||||
# here's some trailing comment as well
|
||||
|
||||
print("Do not format this" )
|
||||
|
||||
def test ():
|
||||
# Leading comments before the statements that should be formatted
|
||||
# Don't duplicate the comments
|
||||
<RANGE_START>print( "format this")
|
||||
# here's some trailing comment as well
|
||||
<RANGE_END>
|
||||
|
||||
print("Do not format this 2" )
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
def test ():
|
||||
# Leading comments before the statements that should be formatted
|
||||
# Don't duplicate the comments
|
||||
print("format this") # trailing end of line comment
|
||||
# here's some trailing comment as well
|
||||
|
||||
print("Do not format this" )
|
||||
|
||||
def test ():
|
||||
# Leading comments before the statements that should be formatted
|
||||
# Don't duplicate the comments
|
||||
print("format this")
|
||||
# here's some trailing comment as well
|
||||
|
||||
|
||||
print("Do not format this 2" )
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/module.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
print("Before range start" )
|
||||
|
||||
<RANGE_START>
|
||||
if a + b :
|
||||
print("formatted" )
|
||||
|
||||
print("still in range" )
|
||||
<RANGE_END>
|
||||
|
||||
print("After range end" )
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
print("Before range start" )
|
||||
|
||||
|
||||
if a + b:
|
||||
print("formatted")
|
||||
|
||||
print("still in range")
|
||||
|
||||
|
||||
print("After range end" )
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/range_narrowing.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
def test ():
|
||||
<RANGE_START>if True:
|
||||
print( "format")
|
||||
elif False:
|
||||
print ( "and this")<RANGE_END>
|
||||
print("not this" )
|
||||
|
||||
print("nor this" )
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
def test ():
|
||||
if True:
|
||||
print("format")
|
||||
elif False:
|
||||
print("and this")
|
||||
print("not this" )
|
||||
|
||||
print("nor this" )
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/regressions.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
class Event:
|
||||
event_name: ClassVar[str]
|
||||
|
||||
@staticmethod
|
||||
def cls_for(event_name: str) -> type[Event]:
|
||||
event_cls = _CONCRETE_EVENT_CLASSES.get(event_name)
|
||||
if event_cls is not <RANGE_START>None:
|
||||
return event_cls<RANGE_END>
|
||||
else:
|
||||
raise ValueError(f"unknown event name '{event_name}'")
|
||||
|
||||
class Event:
|
||||
event_name: ClassVar[str]
|
||||
|
||||
@staticmethod
|
||||
def cls_for(event_name: str) -> type[Event]:
|
||||
event_cls = _CONCRETE_EVENT_CLASSES.get(event_name)
|
||||
if event_cls is not None:
|
||||
<RANGE_START>
|
||||
|
||||
<RANGE_END>
|
||||
return event_cls
|
||||
else:
|
||||
raise ValueError(f"unknown event name '{event_name}'")
|
||||
|
||||
|
||||
# The user starts adding items to a list and then hits save.
|
||||
# Ruff should trim the empty lines
|
||||
a = [
|
||||
1,
|
||||
2,
|
||||
3,<RANGE_START>
|
||||
|
||||
|
||||
<RANGE_END>
|
||||
]
|
||||
|
||||
print("Don't format this" )
|
||||
|
||||
|
||||
# The user removed an argument from a call. Ruff should reformat the entire call
|
||||
call(
|
||||
a,
|
||||
<RANGE_START>
|
||||
<RANGE_END>b,
|
||||
c,
|
||||
d
|
||||
)
|
||||
|
||||
print("Don't format this" )
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# The user adds a new comment at the end:
|
||||
<RANGE_START># <RANGE_END>
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
print("Don't format this" )
|
||||
|
||||
|
||||
def convert_str(value: str) -> str: # Trailing comment
|
||||
"""Return a string as-is."""
|
||||
|
||||
<RANGE_START>
|
||||
|
||||
return value # Trailing comment
|
||||
<RANGE_END>
|
||||
def test ():
|
||||
pass
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
class Event:
|
||||
event_name: ClassVar[str]
|
||||
|
||||
@staticmethod
|
||||
def cls_for(event_name: str) -> type[Event]:
|
||||
event_cls = _CONCRETE_EVENT_CLASSES.get(event_name)
|
||||
if event_cls is not None:
|
||||
return event_cls
|
||||
else:
|
||||
raise ValueError(f"unknown event name '{event_name}'")
|
||||
|
||||
class Event:
|
||||
event_name: ClassVar[str]
|
||||
|
||||
@staticmethod
|
||||
def cls_for(event_name: str) -> type[Event]:
|
||||
event_cls = _CONCRETE_EVENT_CLASSES.get(event_name)
|
||||
if event_cls is not None:
|
||||
return event_cls
|
||||
else:
|
||||
raise ValueError(f"unknown event name '{event_name}'")
|
||||
|
||||
|
||||
# The user starts adding items to a list and then hits save.
|
||||
# Ruff should trim the empty lines
|
||||
a = [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]
|
||||
|
||||
print("Don't format this" )
|
||||
|
||||
|
||||
# The user removed an argument from a call. Ruff should reformat the entire call
|
||||
call(a, b, c, d)
|
||||
|
||||
print("Don't format this" )
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# The user adds a new comment at the end:
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
print("Don't format this" )
|
||||
|
||||
|
||||
def convert_str(value: str) -> str: # Trailing comment
|
||||
"""Return a string as-is."""
|
||||
|
||||
return value # Trailing comment
|
||||
|
||||
|
||||
def test ():
|
||||
pass
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/same_line_body.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
def test(<RANGE_START>a ): <RANGE_END>print("body" )
|
||||
|
||||
|
||||
def test2( a): <RANGE_START>print("body" )<RANGE_END>
|
||||
|
||||
|
||||
def test3( a): <RANGE_START>print("body" )
|
||||
|
||||
print("more" )<RANGE_END>
|
||||
print("after" )
|
||||
|
||||
|
||||
# The if header and the print statement together are longer than 100 characters.
|
||||
# The print statement should either be wrapped to fit at the end of the if statement, or be converted to a
|
||||
# suite body
|
||||
if aaaaaaaaaaaa + bbbbbbbbbbbbbb + cccccccccccccccccc + ddd: <RANGE_START>print("aaaa long body, should wrap or be intented" )<RANGE_END>
|
||||
|
||||
# This print statement is too-long even when intented. It should be wrapped
|
||||
if aaaaaaaaaaaa + bbbbbbbbbbbbbb + cccccccccccccccccc + ddd: <RANGE_START>print("aaaa long body, should wrap or be intented", "more content to make it exceed the 88 chars limit")<RANGE_END>
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
def test(a):
|
||||
print("body")
|
||||
|
||||
|
||||
def test2( a):
|
||||
print("body")
|
||||
|
||||
|
||||
def test3( a):
|
||||
print("body")
|
||||
|
||||
|
||||
print("more")
|
||||
print("after" )
|
||||
|
||||
|
||||
# The if header and the print statement together are longer than 100 characters.
|
||||
# The print statement should either be wrapped to fit at the end of the if statement, or be converted to a
|
||||
# suite body
|
||||
if aaaaaaaaaaaa + bbbbbbbbbbbbbb + cccccccccccccccccc + ddd:
|
||||
print("aaaa long body, should wrap or be intented")
|
||||
|
||||
# This print statement is too-long even when intented. It should be wrapped
|
||||
if aaaaaaaaaaaa + bbbbbbbbbbbbbb + cccccccccccccccccc + ddd:
|
||||
print(
|
||||
"aaaa long body, should wrap or be intented",
|
||||
"more content to make it exceed the 88 chars limit",
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/stub.pyi
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
# Don't collapse the ellipsis if only formatting the ellipsis line.
|
||||
class Test:
|
||||
<RANGE_START>...<RANGE_END>
|
||||
|
||||
class Test2: <RANGE_START>pass<RANGE_END>
|
||||
|
||||
class Test3: <RANGE_START>...<RANGE_END>
|
||||
|
||||
class Test4:
|
||||
# leading comment
|
||||
<RANGE_START>...<RANGE_END>
|
||||
# trailing comment
|
||||
|
||||
|
||||
class Test4:
|
||||
<RANGE_START> ...<RANGE_END>
|
||||
```
|
||||
|
||||
## Outputs
|
||||
### Output 1
|
||||
```
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
line-ending = LineFeed
|
||||
magic-trailing-comma = Respect
|
||||
docstring-code = Disabled
|
||||
docstring-code-line-width = "dynamic"
|
||||
preview = Enabled
|
||||
target_version = Py38
|
||||
source_type = Stub
|
||||
```
|
||||
|
||||
```python
|
||||
# Don't collapse the ellipsis if only formatting the ellipsis line.
|
||||
class Test:
|
||||
...
|
||||
|
||||
class Test2:
|
||||
pass
|
||||
|
||||
class Test3: ...
|
||||
|
||||
class Test4:
|
||||
# leading comment
|
||||
...
|
||||
# trailing comment
|
||||
|
||||
|
||||
class Test4: ...
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/trailing_comments.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
def test1 ():
|
||||
print("hello" )
|
||||
|
||||
<RANGE_START>1 + 2<RANGE_END> # trailing comment
|
||||
print ("world" )
|
||||
|
||||
def test2 ():
|
||||
print("hello" )
|
||||
# FIXME: For some reason the trailing comment here gets not formatted
|
||||
# but is correctly formatted above
|
||||
<RANGE_START>1 + 2 # trailing comment<RANGE_END>
|
||||
print ("world" )
|
||||
|
||||
def test3 ():
|
||||
print("hellO" )
|
||||
|
||||
<RANGE_START>1 + 2 # trailing comment
|
||||
|
||||
# trailing section comment
|
||||
<RANGE_END>
|
||||
|
||||
def test3 ():
|
||||
print("hellO" )
|
||||
|
||||
<RANGE_START>1 + 2 # trailing comment
|
||||
print("more" ) # trailing comment 2
|
||||
# trailing section comment
|
||||
<RANGE_END>
|
||||
|
||||
print( "world" )
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
def test1 ():
|
||||
print("hello" )
|
||||
|
||||
1 + 2 # trailing comment
|
||||
print ("world" )
|
||||
|
||||
def test2 ():
|
||||
print("hello" )
|
||||
# FIXME: For some reason the trailing comment here gets not formatted
|
||||
# but is correctly formatted above
|
||||
1 + 2 # trailing comment
|
||||
print ("world" )
|
||||
|
||||
def test3 ():
|
||||
print("hellO" )
|
||||
|
||||
1 + 2 # trailing comment
|
||||
|
||||
# trailing section comment
|
||||
|
||||
|
||||
def test3 ():
|
||||
print("hellO" )
|
||||
|
||||
1 + 2 # trailing comment
|
||||
print("more") # trailing comment 2
|
||||
# trailing section comment
|
||||
|
||||
|
||||
print( "world" )
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/whitespace_only_range.py
|
||||
---
|
||||
## Input
|
||||
```python
|
||||
def test():
|
||||
pass <RANGE_START>
|
||||
|
||||
<RANGE_END>
|
||||
|
||||
def test_formatted(): pass
|
||||
```
|
||||
|
||||
## Output
|
||||
```python
|
||||
def test():
|
||||
pass
|
||||
|
||||
|
||||
def test_formatted(): pass
|
||||
```
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue