mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 05:25:17 +00:00
Add support for basic Constant::Str
formatting (#3173)
This PR enables us to apply the proper quotation marks, including support for escapes. There are some significant TODOs, especially around implicit concatenations like: ```py ( "abc" "def" ) ``` Which are represented as a single AST node, which requires us to tokenize _within_ the formatter to identify all the individual string parts.
This commit is contained in:
parent
095f005bf4
commit
f967f344fc
24 changed files with 426 additions and 706 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2110,6 +2110,7 @@ dependencies = [
|
||||||
"insta",
|
"insta",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ruff_formatter",
|
"ruff_formatter",
|
||||||
|
"ruff_python",
|
||||||
"ruff_rustpython",
|
"ruff_rustpython",
|
||||||
"ruff_testing_macros",
|
"ruff_testing_macros",
|
||||||
"ruff_text_size",
|
"ruff_text_size",
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
/// See: <https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals>
|
|
||||||
|
|
||||||
pub const TRIPLE_QUOTE_PREFIXES: &[&str] = &[
|
|
||||||
"u\"\"\"", "u'''", "r\"\"\"", "r'''", "U\"\"\"", "U'''", "R\"\"\"", "R'''", "\"\"\"", "'''",
|
|
||||||
];
|
|
||||||
|
|
||||||
pub const SINGLE_QUOTE_PREFIXES: &[&str] = &[
|
|
||||||
"u\"", "u'", "r\"", "r'", "u\"", "u'", "r\"", "r'", "U\"", "U'", "R\"", "R'", "\"", "'",
|
|
||||||
];
|
|
||||||
|
|
||||||
pub const TRIPLE_QUOTE_SUFFIXES: &[&str] = &["\"\"\"", "'''"];
|
|
||||||
|
|
||||||
pub const SINGLE_QUOTE_SUFFIXES: &[&str] = &["\"", "'"];
|
|
|
@ -1,4 +1,3 @@
|
||||||
pub mod constants;
|
|
||||||
pub mod definition;
|
pub mod definition;
|
||||||
pub mod extraction;
|
pub mod extraction;
|
||||||
pub mod google;
|
pub mod google;
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
use crate::docstrings::constants;
|
use ruff_python::string::{
|
||||||
|
SINGLE_QUOTE_PREFIXES, SINGLE_QUOTE_SUFFIXES, TRIPLE_QUOTE_PREFIXES, TRIPLE_QUOTE_SUFFIXES,
|
||||||
|
};
|
||||||
|
|
||||||
/// Strip the leading and trailing quotes from a docstring.
|
/// Strip the leading and trailing quotes from a docstring.
|
||||||
pub fn raw_contents(contents: &str) -> &str {
|
pub fn raw_contents(contents: &str) -> &str {
|
||||||
for pattern in constants::TRIPLE_QUOTE_PREFIXES {
|
for pattern in TRIPLE_QUOTE_PREFIXES {
|
||||||
if contents.starts_with(pattern) {
|
if contents.starts_with(pattern) {
|
||||||
return &contents[pattern.len()..contents.len() - 3];
|
return &contents[pattern.len()..contents.len() - 3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for pattern in constants::SINGLE_QUOTE_PREFIXES {
|
for pattern in SINGLE_QUOTE_PREFIXES {
|
||||||
if contents.starts_with(pattern) {
|
if contents.starts_with(pattern) {
|
||||||
return &contents[pattern.len()..contents.len() - 1];
|
return &contents[pattern.len()..contents.len() - 1];
|
||||||
}
|
}
|
||||||
|
@ -18,10 +20,7 @@ pub fn raw_contents(contents: &str) -> &str {
|
||||||
/// Return the leading quote string for a docstring (e.g., `"""`).
|
/// Return the leading quote string for a docstring (e.g., `"""`).
|
||||||
pub fn leading_quote(content: &str) -> Option<&str> {
|
pub fn leading_quote(content: &str) -> Option<&str> {
|
||||||
if let Some(first_line) = content.lines().next() {
|
if let Some(first_line) = content.lines().next() {
|
||||||
for pattern in constants::TRIPLE_QUOTE_PREFIXES
|
for pattern in TRIPLE_QUOTE_PREFIXES.iter().chain(SINGLE_QUOTE_PREFIXES) {
|
||||||
.iter()
|
|
||||||
.chain(constants::SINGLE_QUOTE_PREFIXES)
|
|
||||||
{
|
|
||||||
if first_line.starts_with(pattern) {
|
if first_line.starts_with(pattern) {
|
||||||
return Some(pattern);
|
return Some(pattern);
|
||||||
}
|
}
|
||||||
|
@ -32,9 +31,9 @@ pub fn leading_quote(content: &str) -> Option<&str> {
|
||||||
|
|
||||||
/// Return the trailing quote string for a docstring (e.g., `"""`).
|
/// Return the trailing quote string for a docstring (e.g., `"""`).
|
||||||
pub fn trailing_quote(content: &str) -> Option<&&str> {
|
pub fn trailing_quote(content: &str) -> Option<&&str> {
|
||||||
constants::TRIPLE_QUOTE_SUFFIXES
|
TRIPLE_QUOTE_SUFFIXES
|
||||||
.iter()
|
.iter()
|
||||||
.chain(constants::SINGLE_QUOTE_SUFFIXES)
|
.chain(SINGLE_QUOTE_SUFFIXES)
|
||||||
.find(|&pattern| content.ends_with(pattern))
|
.find(|&pattern| content.ends_with(pattern))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use ruff_macros::{define_violation, derive_message_formats};
|
use ruff_macros::{define_violation, derive_message_formats};
|
||||||
|
use ruff_python::string::TRIPLE_QUOTE_PREFIXES;
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::ast::whitespace::LinesWithTrailingNewline;
|
use crate::ast::whitespace::LinesWithTrailingNewline;
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::docstrings::constants;
|
|
||||||
use crate::docstrings::definition::{DefinitionKind, Docstring};
|
use crate::docstrings::definition::{DefinitionKind, Docstring};
|
||||||
use crate::fix::Fix;
|
use crate::fix::Fix;
|
||||||
use crate::message::Location;
|
use crate::message::Location;
|
||||||
|
@ -54,7 +54,7 @@ pub fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstring) {
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if constants::TRIPLE_QUOTE_PREFIXES.contains(&first_line) {
|
if TRIPLE_QUOTE_PREFIXES.contains(&first_line) {
|
||||||
if checker
|
if checker
|
||||||
.settings
|
.settings
|
||||||
.rules
|
.rules
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
|
/// See: <https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals>
|
||||||
|
pub const TRIPLE_QUOTE_PREFIXES: &[&str] = &[
|
||||||
|
"u\"\"\"", "u'''", "r\"\"\"", "r'''", "U\"\"\"", "U'''", "R\"\"\"", "R'''", "\"\"\"", "'''",
|
||||||
|
];
|
||||||
|
pub const SINGLE_QUOTE_PREFIXES: &[&str] = &[
|
||||||
|
"u\"", "u'", "r\"", "r'", "u\"", "u'", "r\"", "r'", "U\"", "U'", "R\"", "R'", "\"", "'",
|
||||||
|
];
|
||||||
|
pub const TRIPLE_QUOTE_SUFFIXES: &[&str] = &["\"\"\"", "'''"];
|
||||||
|
pub const SINGLE_QUOTE_SUFFIXES: &[&str] = &["\"", "'"];
|
||||||
|
|
||||||
pub static STRING_QUOTE_PREFIX_REGEX: Lazy<Regex> =
|
pub static STRING_QUOTE_PREFIX_REGEX: Lazy<Regex> =
|
||||||
Lazy::new(|| Regex::new(r#"^(?i)[urb]*['"](?P<raw>.*)['"]$"#).unwrap());
|
Lazy::new(|| Regex::new(r#"^(?i)[urb]*['"](?P<raw>.*)['"]$"#).unwrap());
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ rust-version = { workspace = true }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ruff_formatter = { path = "../ruff_formatter" }
|
ruff_formatter = { path = "../ruff_formatter" }
|
||||||
|
ruff_python = { path = "../ruff_python" }
|
||||||
ruff_rustpython = { path = "../ruff_rustpython" }
|
ruff_rustpython = { path = "../ruff_rustpython" }
|
||||||
ruff_text_size = { path = "../ruff_text_size" }
|
ruff_text_size = { path = "../ruff_text_size" }
|
||||||
|
|
||||||
|
|
23
crates/ruff_python_formatter/src/core/helpers.rs
Normal file
23
crates/ruff_python_formatter/src/core/helpers.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use ruff_python::string::{
|
||||||
|
SINGLE_QUOTE_PREFIXES, SINGLE_QUOTE_SUFFIXES, TRIPLE_QUOTE_PREFIXES, TRIPLE_QUOTE_SUFFIXES,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Return the leading quote string for a docstring (e.g., `"""`).
|
||||||
|
pub fn leading_quote(content: &str) -> Option<&str> {
|
||||||
|
if let Some(first_line) = content.lines().next() {
|
||||||
|
for pattern in TRIPLE_QUOTE_PREFIXES.iter().chain(SINGLE_QUOTE_PREFIXES) {
|
||||||
|
if first_line.starts_with(pattern) {
|
||||||
|
return Some(pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the trailing quote string for a docstring (e.g., `"""`).
|
||||||
|
pub fn trailing_quote(content: &str) -> Option<&&str> {
|
||||||
|
TRIPLE_QUOTE_SUFFIXES
|
||||||
|
.iter()
|
||||||
|
.chain(SINGLE_QUOTE_SUFFIXES)
|
||||||
|
.find(|&pattern| content.ends_with(pattern))
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod helpers;
|
||||||
pub mod locator;
|
pub mod locator;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod visitor;
|
pub mod visitor;
|
||||||
|
|
|
@ -13,6 +13,7 @@ use crate::cst::{
|
||||||
Arguments, Boolop, Cmpop, Comprehension, Expr, ExprKind, Keyword, Operator, Unaryop,
|
Arguments, Boolop, Cmpop, Comprehension, Expr, ExprKind, Keyword, Operator, Unaryop,
|
||||||
};
|
};
|
||||||
use crate::format::helpers::{is_self_closing, is_simple_power, is_simple_slice};
|
use crate::format::helpers::{is_self_closing, is_simple_power, is_simple_slice};
|
||||||
|
use crate::format::strings::string_literal;
|
||||||
use crate::shared_traits::AsFormat;
|
use crate::shared_traits::AsFormat;
|
||||||
use crate::trivia::{Parenthesize, Relationship, TriviaKind};
|
use crate::trivia::{Parenthesize, Relationship, TriviaKind};
|
||||||
|
|
||||||
|
@ -128,8 +129,6 @@ fn format_tuple(
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
[soft_block_indent(&format_with(|f| {
|
[soft_block_indent(&format_with(|f| {
|
||||||
// TODO(charlie): If the magic trailing comma isn't present, and the
|
|
||||||
// tuple is _already_ expanded, we're not supposed to add this.
|
|
||||||
let magic_trailing_comma = expr
|
let magic_trailing_comma = expr
|
||||||
.trivia
|
.trivia
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -641,10 +640,21 @@ fn format_joined_str(
|
||||||
fn format_constant(
|
fn format_constant(
|
||||||
f: &mut Formatter<ASTFormatContext<'_>>,
|
f: &mut Formatter<ASTFormatContext<'_>>,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
_constant: &Constant,
|
constant: &Constant,
|
||||||
_kind: Option<&str>,
|
_kind: Option<&str>,
|
||||||
) -> FormatResult<()> {
|
) -> FormatResult<()> {
|
||||||
write!(f, [literal(Range::from_located(expr))])?;
|
match constant {
|
||||||
|
Constant::None => write!(f, [text("None")])?,
|
||||||
|
Constant::Bool(value) => {
|
||||||
|
if *value {
|
||||||
|
write!(f, [text("True")])?;
|
||||||
|
} else {
|
||||||
|
write!(f, [text("False")])?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constant::Str(_) => write!(f, [string_literal(expr)])?,
|
||||||
|
_ => write!(f, [literal(Range::from_located(expr))])?,
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,5 +10,6 @@ mod expr;
|
||||||
mod helpers;
|
mod helpers;
|
||||||
mod operator;
|
mod operator;
|
||||||
mod stmt;
|
mod stmt;
|
||||||
|
mod strings;
|
||||||
mod unaryop;
|
mod unaryop;
|
||||||
mod withitem;
|
mod withitem;
|
||||||
|
|
240
crates/ruff_python_formatter/src/format/strings.rs
Normal file
240
crates/ruff_python_formatter/src/format/strings.rs
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
use rustpython_parser::{Mode, Tok};
|
||||||
|
|
||||||
|
use ruff_formatter::prelude::*;
|
||||||
|
use ruff_formatter::{write, Format};
|
||||||
|
use ruff_text_size::TextSize;
|
||||||
|
|
||||||
|
use crate::context::ASTFormatContext;
|
||||||
|
use crate::core::helpers::{leading_quote, trailing_quote};
|
||||||
|
use crate::core::types::Range;
|
||||||
|
use crate::cst::Expr;
|
||||||
|
use crate::trivia::Parenthesize;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
pub struct StringLiteralPart {
|
||||||
|
range: Range,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Format<ASTFormatContext<'_>> for StringLiteralPart {
|
||||||
|
fn fmt(&self, f: &mut Formatter<ASTFormatContext<'_>>) -> FormatResult<()> {
|
||||||
|
let (source, start, end) = f.context().locator().slice(self.range);
|
||||||
|
|
||||||
|
// Extract leading and trailing quotes.
|
||||||
|
let content = &source[start..end];
|
||||||
|
let leading_quote = leading_quote(content).unwrap();
|
||||||
|
let trailing_quote = trailing_quote(content).unwrap();
|
||||||
|
let body = &content[leading_quote.len()..content.len() - trailing_quote.len()];
|
||||||
|
|
||||||
|
// Determine the correct quote style.
|
||||||
|
// TODO(charlie): Make this parameterizable.
|
||||||
|
let mut squotes: usize = 0;
|
||||||
|
let mut dquotes: usize = 0;
|
||||||
|
for char in body.chars() {
|
||||||
|
if char == '\'' {
|
||||||
|
squotes += 1;
|
||||||
|
} else if char == '"' {
|
||||||
|
dquotes += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut is_raw = false;
|
||||||
|
if leading_quote.contains('r') {
|
||||||
|
is_raw = true;
|
||||||
|
f.write_element(FormatElement::StaticText { text: "r" })?;
|
||||||
|
} else if leading_quote.contains('R') {
|
||||||
|
is_raw = true;
|
||||||
|
f.write_element(FormatElement::StaticText { text: "R" })?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if trailing_quote.len() == 1 {
|
||||||
|
// Single-quoted string.
|
||||||
|
if dquotes == 0 || squotes > 0 {
|
||||||
|
// If the body doesn't contain any double quotes, or it contains both single and
|
||||||
|
// double quotes, use double quotes.
|
||||||
|
f.write_element(FormatElement::StaticText { text: "\"" })?;
|
||||||
|
f.write_element(FormatElement::DynamicText {
|
||||||
|
text: if is_raw {
|
||||||
|
body.into()
|
||||||
|
} else {
|
||||||
|
double_escape(body).into()
|
||||||
|
},
|
||||||
|
source_position: TextSize::default(),
|
||||||
|
})?;
|
||||||
|
f.write_element(FormatElement::StaticText { text: "\"" })?;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
f.write_element(FormatElement::StaticText { text: "'" })?;
|
||||||
|
f.write_element(FormatElement::DynamicText {
|
||||||
|
text: if is_raw {
|
||||||
|
body.into()
|
||||||
|
} else {
|
||||||
|
single_escape(body).into()
|
||||||
|
},
|
||||||
|
source_position: TextSize::default(),
|
||||||
|
})?;
|
||||||
|
f.write_element(FormatElement::StaticText { text: "'" })?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
} else if trailing_quote.len() == 3 {
|
||||||
|
// Triple-quoted string.
|
||||||
|
if body.starts_with("\"\"\"") || body.ends_with('"') {
|
||||||
|
// We only need to use single quotes if the string body starts with three or more
|
||||||
|
// double quotes, or ends with a double quote. Converting to double quotes in those
|
||||||
|
// cases would cause a syntax error.
|
||||||
|
f.write_element(FormatElement::StaticText { text: "'''" })?;
|
||||||
|
f.write_element(FormatElement::DynamicText {
|
||||||
|
text: body.to_string().into_boxed_str(),
|
||||||
|
source_position: TextSize::default(),
|
||||||
|
})?;
|
||||||
|
f.write_element(FormatElement::StaticText { text: "'''" })?;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
f.write_element(FormatElement::StaticText { text: "\"\"\"" })?;
|
||||||
|
f.write_element(FormatElement::DynamicText {
|
||||||
|
text: body.to_string().into_boxed_str(),
|
||||||
|
source_position: TextSize::default(),
|
||||||
|
})?;
|
||||||
|
f.write_element(FormatElement::StaticText { text: "\"\"\"" })?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("Invalid quote length: {}", trailing_quote.len());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub const fn string_literal_part(range: Range) -> StringLiteralPart {
|
||||||
|
StringLiteralPart { range }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct StringLiteral<'a> {
|
||||||
|
expr: &'a Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Format<ASTFormatContext<'_>> for StringLiteral<'_> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<ASTFormatContext<'_>>) -> FormatResult<()> {
|
||||||
|
let expr = self.expr;
|
||||||
|
|
||||||
|
// TODO(charlie): This tokenization needs to happen earlier, so that we can attach
|
||||||
|
// comments to individual string literals.
|
||||||
|
let (source, start, end) = f.context().locator().slice(Range::from_located(expr));
|
||||||
|
let elts =
|
||||||
|
rustpython_parser::lexer::lex_located(&source[start..end], Mode::Module, expr.location)
|
||||||
|
.flatten()
|
||||||
|
.filter_map(|(start, tok, end)| {
|
||||||
|
if matches!(tok, Tok::String { .. }) {
|
||||||
|
Some(Range::new(start, end))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
[group(&format_with(|f| {
|
||||||
|
if matches!(expr.parentheses, Parenthesize::IfExpanded) {
|
||||||
|
write!(f, [if_group_breaks(&text("("))])?;
|
||||||
|
}
|
||||||
|
for (i, elt) in elts.iter().enumerate() {
|
||||||
|
write!(f, [string_literal_part(*elt)])?;
|
||||||
|
if i < elts.len() - 1 {
|
||||||
|
write!(f, [soft_line_break_or_space()])?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matches!(expr.parentheses, Parenthesize::IfExpanded) {
|
||||||
|
write!(f, [if_group_breaks(&text(")"))])?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}))]
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub const fn string_literal(expr: &Expr) -> StringLiteral {
|
||||||
|
StringLiteral { expr }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Escape a string body to be used in a string literal with double quotes.
|
||||||
|
fn double_escape(text: &str) -> String {
|
||||||
|
let mut escaped = String::with_capacity(text.len());
|
||||||
|
let mut chars = text.chars().peekable();
|
||||||
|
while let Some(ch) = chars.next() {
|
||||||
|
if ch == '\\' {
|
||||||
|
let Some(next) = chars.peek() else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
if *next == '\'' {
|
||||||
|
chars.next();
|
||||||
|
escaped.push('\'');
|
||||||
|
} else if *next == '"' {
|
||||||
|
chars.next();
|
||||||
|
escaped.push('"');
|
||||||
|
} else if *next == '\\' {
|
||||||
|
chars.next();
|
||||||
|
escaped.push('\\');
|
||||||
|
escaped.push(ch);
|
||||||
|
} else {
|
||||||
|
escaped.push(ch);
|
||||||
|
}
|
||||||
|
} else if ch == '"' {
|
||||||
|
escaped.push('\\');
|
||||||
|
escaped.push('"');
|
||||||
|
} else {
|
||||||
|
escaped.push(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
escaped
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Escape a string body to be used in a string literal with single quotes.
|
||||||
|
fn single_escape(text: &str) -> String {
|
||||||
|
let mut escaped = String::with_capacity(text.len());
|
||||||
|
let mut chars = text.chars().peekable();
|
||||||
|
while let Some(ch) = chars.next() {
|
||||||
|
if ch == '\\' {
|
||||||
|
let Some(next) = chars.peek() else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
if *next == '"' {
|
||||||
|
chars.next();
|
||||||
|
escaped.push('"');
|
||||||
|
} else if *next == '\'' {
|
||||||
|
chars.next();
|
||||||
|
escaped.push('\'');
|
||||||
|
} else if *next == '\\' {
|
||||||
|
chars.next();
|
||||||
|
escaped.push('\\');
|
||||||
|
escaped.push(ch);
|
||||||
|
} else {
|
||||||
|
escaped.push(ch);
|
||||||
|
}
|
||||||
|
} else if ch == '\'' {
|
||||||
|
escaped.push('\\');
|
||||||
|
escaped.push('\'');
|
||||||
|
} else {
|
||||||
|
escaped.push(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
escaped
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_double_escape() {
|
||||||
|
assert_eq!(double_escape(r#"It\'s mine"#), r#"It's mine"#);
|
||||||
|
assert_eq!(double_escape(r#"It\'s "mine""#), r#"It's \"mine\""#);
|
||||||
|
assert_eq!(double_escape(r#"It\\'s mine"#), r#"It\\'s mine"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_single_escape() {
|
||||||
|
assert_eq!(single_escape(r#"It's \"mine\""#), r#"It\'s "mine""#);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,49 +0,0 @@
|
||||||
---
|
|
||||||
source: crates/ruff_python_formatter/src/lib.rs
|
|
||||||
expression: snapshot
|
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/bracketmatch.py
|
|
||||||
---
|
|
||||||
## Input
|
|
||||||
|
|
||||||
```py
|
|
||||||
for ((x in {}) or {})['a'] in x:
|
|
||||||
pass
|
|
||||||
pem_spam = lambda l, spam = {
|
|
||||||
"x": 3
|
|
||||||
}: not spam.get(l.strip())
|
|
||||||
lambda x=lambda y={1: 3}: y['x':lambda y: {1: 2}]: x
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Differences
|
|
||||||
|
|
||||||
```diff
|
|
||||||
--- Black
|
|
||||||
+++ Ruff
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-for ((x in {}) or {})["a"] in x:
|
|
||||||
+for ((x in {}) or {})['a'] in x:
|
|
||||||
pass
|
|
||||||
pem_spam = lambda l, spam={"x": 3}: not spam.get(l.strip())
|
|
||||||
-lambda x=lambda y={1: 3}: y["x" : lambda y: {1: 2}]: x
|
|
||||||
+lambda x=lambda y={1: 3}: y['x' : lambda y: {1: 2}]: x
|
|
||||||
```
|
|
||||||
|
|
||||||
## Ruff Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
for ((x in {}) or {})['a'] in x:
|
|
||||||
pass
|
|
||||||
pem_spam = lambda l, spam={"x": 3}: not spam.get(l.strip())
|
|
||||||
lambda x=lambda y={1: 3}: y['x' : lambda y: {1: 2}]: x
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
for ((x in {}) or {})["a"] in x:
|
|
||||||
pass
|
|
||||||
pem_spam = lambda l, spam={"x": 3}: not spam.get(l.strip())
|
|
||||||
lambda x=lambda y={1: 3}: y["x" : lambda y: {1: 2}]: x
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -1,319 +0,0 @@
|
||||||
---
|
|
||||||
source: crates/ruff_python_formatter/src/lib.rs
|
|
||||||
expression: snapshot
|
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/collections.py
|
|
||||||
---
|
|
||||||
## Input
|
|
||||||
|
|
||||||
```py
|
|
||||||
import core, time, a
|
|
||||||
|
|
||||||
from . import A, B, C
|
|
||||||
|
|
||||||
# keeps existing trailing comma
|
|
||||||
from foo import (
|
|
||||||
bar,
|
|
||||||
)
|
|
||||||
|
|
||||||
# also keeps existing structure
|
|
||||||
from foo import (
|
|
||||||
baz,
|
|
||||||
qux,
|
|
||||||
)
|
|
||||||
|
|
||||||
# `as` works as well
|
|
||||||
from foo import (
|
|
||||||
xyzzy as magic,
|
|
||||||
)
|
|
||||||
|
|
||||||
a = {1,2,3,}
|
|
||||||
b = {
|
|
||||||
1,2,
|
|
||||||
3}
|
|
||||||
c = {
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
}
|
|
||||||
x = 1,
|
|
||||||
y = narf(),
|
|
||||||
nested = {(1,2,3),(4,5,6),}
|
|
||||||
nested_no_trailing_comma = {(1,2,3),(4,5,6)}
|
|
||||||
nested_long_lines = ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "cccccccccccccccccccccccccccccccccccccccc", (1, 2, 3), "dddddddddddddddddddddddddddddddddddddddd"]
|
|
||||||
{"oneple": (1,),}
|
|
||||||
{"oneple": (1,)}
|
|
||||||
['ls', 'lsoneple/%s' % (foo,)]
|
|
||||||
x = {"oneple": (1,)}
|
|
||||||
y = {"oneple": (1,),}
|
|
||||||
assert False, ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa wraps %s" % bar)
|
|
||||||
|
|
||||||
# looping over a 1-tuple should also not get wrapped
|
|
||||||
for x in (1,):
|
|
||||||
pass
|
|
||||||
for (x,) in (1,), (2,), (3,):
|
|
||||||
pass
|
|
||||||
|
|
||||||
[1, 2, 3,]
|
|
||||||
|
|
||||||
division_result_tuple = (6/2,)
|
|
||||||
print("foo %r", (foo.bar,))
|
|
||||||
|
|
||||||
if True:
|
|
||||||
IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = (
|
|
||||||
Config.IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING
|
|
||||||
| {pylons.controllers.WSGIController}
|
|
||||||
)
|
|
||||||
|
|
||||||
if True:
|
|
||||||
ec2client.get_waiter('instance_stopped').wait(
|
|
||||||
InstanceIds=[instance.id],
|
|
||||||
WaiterConfig={
|
|
||||||
'Delay': 5,
|
|
||||||
})
|
|
||||||
ec2client.get_waiter("instance_stopped").wait(
|
|
||||||
InstanceIds=[instance.id],
|
|
||||||
WaiterConfig={"Delay": 5,},
|
|
||||||
)
|
|
||||||
ec2client.get_waiter("instance_stopped").wait(
|
|
||||||
InstanceIds=[instance.id], WaiterConfig={"Delay": 5,},
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Differences
|
|
||||||
|
|
||||||
```diff
|
|
||||||
--- Black
|
|
||||||
+++ Ruff
|
|
||||||
@@ -47,7 +47,7 @@
|
|
||||||
"oneple": (1,),
|
|
||||||
}
|
|
||||||
{"oneple": (1,)}
|
|
||||||
-["ls", "lsoneple/%s" % (foo,)]
|
|
||||||
+['ls', 'lsoneple/%s' % (foo,)]
|
|
||||||
x = {"oneple": (1,)}
|
|
||||||
y = {
|
|
||||||
"oneple": (1,),
|
|
||||||
@@ -79,10 +79,10 @@
|
|
||||||
)
|
|
||||||
|
|
||||||
if True:
|
|
||||||
- ec2client.get_waiter("instance_stopped").wait(
|
|
||||||
+ ec2client.get_waiter('instance_stopped').wait(
|
|
||||||
InstanceIds=[instance.id],
|
|
||||||
WaiterConfig={
|
|
||||||
- "Delay": 5,
|
|
||||||
+ 'Delay': 5,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
ec2client.get_waiter("instance_stopped").wait(
|
|
||||||
```
|
|
||||||
|
|
||||||
## Ruff Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
import core, time, a
|
|
||||||
|
|
||||||
from . import A, B, C
|
|
||||||
|
|
||||||
# keeps existing trailing comma
|
|
||||||
from foo import (
|
|
||||||
bar,
|
|
||||||
)
|
|
||||||
|
|
||||||
# also keeps existing structure
|
|
||||||
from foo import (
|
|
||||||
baz,
|
|
||||||
qux,
|
|
||||||
)
|
|
||||||
|
|
||||||
# `as` works as well
|
|
||||||
from foo import (
|
|
||||||
xyzzy as magic,
|
|
||||||
)
|
|
||||||
|
|
||||||
a = {
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
}
|
|
||||||
b = {1, 2, 3}
|
|
||||||
c = {
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
}
|
|
||||||
x = (1,)
|
|
||||||
y = (narf(),)
|
|
||||||
nested = {
|
|
||||||
(1, 2, 3),
|
|
||||||
(4, 5, 6),
|
|
||||||
}
|
|
||||||
nested_no_trailing_comma = {(1, 2, 3), (4, 5, 6)}
|
|
||||||
nested_long_lines = [
|
|
||||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
||||||
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
||||||
"cccccccccccccccccccccccccccccccccccccccc",
|
|
||||||
(1, 2, 3),
|
|
||||||
"dddddddddddddddddddddddddddddddddddddddd",
|
|
||||||
]
|
|
||||||
{
|
|
||||||
"oneple": (1,),
|
|
||||||
}
|
|
||||||
{"oneple": (1,)}
|
|
||||||
['ls', 'lsoneple/%s' % (foo,)]
|
|
||||||
x = {"oneple": (1,)}
|
|
||||||
y = {
|
|
||||||
"oneple": (1,),
|
|
||||||
}
|
|
||||||
assert False, (
|
|
||||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa wraps %s"
|
|
||||||
% bar
|
|
||||||
)
|
|
||||||
|
|
||||||
# looping over a 1-tuple should also not get wrapped
|
|
||||||
for x in (1,):
|
|
||||||
pass
|
|
||||||
for (x,) in (1,), (2,), (3,):
|
|
||||||
pass
|
|
||||||
|
|
||||||
[
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
]
|
|
||||||
|
|
||||||
division_result_tuple = (6 / 2,)
|
|
||||||
print("foo %r", (foo.bar,))
|
|
||||||
|
|
||||||
if True:
|
|
||||||
IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = (
|
|
||||||
Config.IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING
|
|
||||||
| {pylons.controllers.WSGIController}
|
|
||||||
)
|
|
||||||
|
|
||||||
if True:
|
|
||||||
ec2client.get_waiter('instance_stopped').wait(
|
|
||||||
InstanceIds=[instance.id],
|
|
||||||
WaiterConfig={
|
|
||||||
'Delay': 5,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
ec2client.get_waiter("instance_stopped").wait(
|
|
||||||
InstanceIds=[instance.id],
|
|
||||||
WaiterConfig={
|
|
||||||
"Delay": 5,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
ec2client.get_waiter("instance_stopped").wait(
|
|
||||||
InstanceIds=[instance.id],
|
|
||||||
WaiterConfig={
|
|
||||||
"Delay": 5,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
import core, time, a
|
|
||||||
|
|
||||||
from . import A, B, C
|
|
||||||
|
|
||||||
# keeps existing trailing comma
|
|
||||||
from foo import (
|
|
||||||
bar,
|
|
||||||
)
|
|
||||||
|
|
||||||
# also keeps existing structure
|
|
||||||
from foo import (
|
|
||||||
baz,
|
|
||||||
qux,
|
|
||||||
)
|
|
||||||
|
|
||||||
# `as` works as well
|
|
||||||
from foo import (
|
|
||||||
xyzzy as magic,
|
|
||||||
)
|
|
||||||
|
|
||||||
a = {
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
}
|
|
||||||
b = {1, 2, 3}
|
|
||||||
c = {
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
}
|
|
||||||
x = (1,)
|
|
||||||
y = (narf(),)
|
|
||||||
nested = {
|
|
||||||
(1, 2, 3),
|
|
||||||
(4, 5, 6),
|
|
||||||
}
|
|
||||||
nested_no_trailing_comma = {(1, 2, 3), (4, 5, 6)}
|
|
||||||
nested_long_lines = [
|
|
||||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
||||||
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
||||||
"cccccccccccccccccccccccccccccccccccccccc",
|
|
||||||
(1, 2, 3),
|
|
||||||
"dddddddddddddddddddddddddddddddddddddddd",
|
|
||||||
]
|
|
||||||
{
|
|
||||||
"oneple": (1,),
|
|
||||||
}
|
|
||||||
{"oneple": (1,)}
|
|
||||||
["ls", "lsoneple/%s" % (foo,)]
|
|
||||||
x = {"oneple": (1,)}
|
|
||||||
y = {
|
|
||||||
"oneple": (1,),
|
|
||||||
}
|
|
||||||
assert False, (
|
|
||||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa wraps %s"
|
|
||||||
% bar
|
|
||||||
)
|
|
||||||
|
|
||||||
# looping over a 1-tuple should also not get wrapped
|
|
||||||
for x in (1,):
|
|
||||||
pass
|
|
||||||
for (x,) in (1,), (2,), (3,):
|
|
||||||
pass
|
|
||||||
|
|
||||||
[
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
]
|
|
||||||
|
|
||||||
division_result_tuple = (6 / 2,)
|
|
||||||
print("foo %r", (foo.bar,))
|
|
||||||
|
|
||||||
if True:
|
|
||||||
IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = (
|
|
||||||
Config.IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING
|
|
||||||
| {pylons.controllers.WSGIController}
|
|
||||||
)
|
|
||||||
|
|
||||||
if True:
|
|
||||||
ec2client.get_waiter("instance_stopped").wait(
|
|
||||||
InstanceIds=[instance.id],
|
|
||||||
WaiterConfig={
|
|
||||||
"Delay": 5,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
ec2client.get_waiter("instance_stopped").wait(
|
|
||||||
InstanceIds=[instance.id],
|
|
||||||
WaiterConfig={
|
|
||||||
"Delay": 5,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
ec2client.get_waiter("instance_stopped").wait(
|
|
||||||
InstanceIds=[instance.id],
|
|
||||||
WaiterConfig={
|
|
||||||
"Delay": 5,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ instruction()#comment with bad spacing
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -1,31 +1,31 @@
|
@@ -1,8 +1,8 @@
|
||||||
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||||
- MyLovelyCompanyTeamProjectComponent, # NOT DRY
|
- MyLovelyCompanyTeamProjectComponent, # NOT DRY
|
||||||
+ MyLovelyCompanyTeamProjectComponent,
|
+ MyLovelyCompanyTeamProjectComponent,
|
||||||
|
@ -189,52 +189,25 @@ instruction()#comment with bad spacing
|
||||||
)
|
)
|
||||||
|
|
||||||
# Please keep __all__ alphabetized within each category.
|
# Please keep __all__ alphabetized within each category.
|
||||||
|
@@ -13,7 +13,7 @@
|
||||||
__all__ = [
|
"Callable",
|
||||||
# Super-special typing primitives.
|
"ClassVar",
|
||||||
- "Any",
|
|
||||||
- "Callable",
|
|
||||||
- "ClassVar",
|
|
||||||
+ 'Any',
|
|
||||||
+ 'Callable',
|
|
||||||
+ 'ClassVar',
|
|
||||||
# ABCs (from collections.abc).
|
# ABCs (from collections.abc).
|
||||||
- "AbstractSet", # collections.abc.Set.
|
- "AbstractSet", # collections.abc.Set.
|
||||||
- "ByteString",
|
+ "AbstractSet",
|
||||||
- "Container",
|
"ByteString",
|
||||||
+ 'AbstractSet',
|
"Container",
|
||||||
+ 'ByteString',
|
|
||||||
+ 'Container',
|
|
||||||
# Concrete collection types.
|
# Concrete collection types.
|
||||||
- "Counter",
|
@@ -24,7 +24,7 @@
|
||||||
- "Deque",
|
"List",
|
||||||
- "Dict",
|
"Set",
|
||||||
- "DefaultDict",
|
"FrozenSet",
|
||||||
- "List",
|
|
||||||
- "Set",
|
|
||||||
- "FrozenSet",
|
|
||||||
- "NamedTuple", # Not really a type.
|
- "NamedTuple", # Not really a type.
|
||||||
- "Generator",
|
+ "NamedTuple",
|
||||||
+ 'Counter',
|
"Generator",
|
||||||
+ 'Deque',
|
|
||||||
+ 'Dict',
|
|
||||||
+ 'DefaultDict',
|
|
||||||
+ 'List',
|
|
||||||
+ 'Set',
|
|
||||||
+ 'FrozenSet',
|
|
||||||
+ 'NamedTuple',
|
|
||||||
+ 'Generator',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
not_shareables = [
|
@@ -54,32 +54,39 @@
|
||||||
@@ -48,38 +48,45 @@
|
|
||||||
SubBytes(b"spam"),
|
|
||||||
]
|
|
||||||
|
|
||||||
-if "PYTHON" in os.environ:
|
|
||||||
+if 'PYTHON' in os.environ:
|
|
||||||
add_compiler(compiler_from_env())
|
|
||||||
else:
|
|
||||||
# for compiler in compilers.values():
|
# for compiler in compilers.values():
|
||||||
# add_compiler(compiler)
|
# add_compiler(compiler)
|
||||||
add_compiler(compilers[(7.0, 32)])
|
add_compiler(compilers[(7.0, 32)])
|
||||||
|
@ -284,7 +257,7 @@ instruction()#comment with bad spacing
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
# no newline before or after
|
# no newline before or after
|
||||||
@@ -103,47 +110,47 @@
|
@@ -103,42 +110,42 @@
|
||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
call2(
|
call2(
|
||||||
|
@ -323,12 +296,11 @@ instruction()#comment with bad spacing
|
||||||
]
|
]
|
||||||
lcomp3 = [
|
lcomp3 = [
|
||||||
# This one is actually too long to fit in a single line.
|
# This one is actually too long to fit in a single line.
|
||||||
- element.split("\n", 1)[0]
|
element.split("\n", 1)[0]
|
||||||
- # yup
|
- # yup
|
||||||
- for element in collection.select_elements()
|
- for element in collection.select_elements()
|
||||||
- # right
|
- # right
|
||||||
- if element is not None
|
- if element is not None
|
||||||
+ element.split('\n', 1)[0]
|
|
||||||
+ for # yup
|
+ for # yup
|
||||||
+ element in collection.select_elements()
|
+ element in collection.select_elements()
|
||||||
+ if # right
|
+ if # right
|
||||||
|
@ -346,12 +318,6 @@ instruction()#comment with bad spacing
|
||||||
|
|
||||||
# let's return
|
# let's return
|
||||||
return Node(
|
return Node(
|
||||||
syms.simple_stmt,
|
|
||||||
- [Node(statement, result), Leaf(token.NEWLINE, "\n")], # FIXME: \r\n?
|
|
||||||
+ [Node(statement, result), Leaf(token.NEWLINE, '\n')], # FIXME: \r\n?
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@@ -167,7 +174,7 @@
|
@@ -167,7 +174,7 @@
|
||||||
#######################
|
#######################
|
||||||
|
|
||||||
|
@ -377,23 +343,23 @@ from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
# Super-special typing primitives.
|
# Super-special typing primitives.
|
||||||
'Any',
|
"Any",
|
||||||
'Callable',
|
"Callable",
|
||||||
'ClassVar',
|
"ClassVar",
|
||||||
# ABCs (from collections.abc).
|
# ABCs (from collections.abc).
|
||||||
'AbstractSet',
|
"AbstractSet",
|
||||||
'ByteString',
|
"ByteString",
|
||||||
'Container',
|
"Container",
|
||||||
# Concrete collection types.
|
# Concrete collection types.
|
||||||
'Counter',
|
"Counter",
|
||||||
'Deque',
|
"Deque",
|
||||||
'Dict',
|
"Dict",
|
||||||
'DefaultDict',
|
"DefaultDict",
|
||||||
'List',
|
"List",
|
||||||
'Set',
|
"Set",
|
||||||
'FrozenSet',
|
"FrozenSet",
|
||||||
'NamedTuple',
|
"NamedTuple",
|
||||||
'Generator',
|
"Generator",
|
||||||
]
|
]
|
||||||
|
|
||||||
not_shareables = [
|
not_shareables = [
|
||||||
|
@ -416,7 +382,7 @@ not_shareables = [
|
||||||
SubBytes(b"spam"),
|
SubBytes(b"spam"),
|
||||||
]
|
]
|
||||||
|
|
||||||
if 'PYTHON' in os.environ:
|
if "PYTHON" in os.environ:
|
||||||
add_compiler(compiler_from_env())
|
add_compiler(compiler_from_env())
|
||||||
else:
|
else:
|
||||||
# for compiler in compilers.values():
|
# for compiler in compilers.values():
|
||||||
|
@ -501,7 +467,7 @@ short
|
||||||
]
|
]
|
||||||
lcomp3 = [
|
lcomp3 = [
|
||||||
# This one is actually too long to fit in a single line.
|
# This one is actually too long to fit in a single line.
|
||||||
element.split('\n', 1)[0]
|
element.split("\n", 1)[0]
|
||||||
for # yup
|
for # yup
|
||||||
element in collection.select_elements()
|
element in collection.select_elements()
|
||||||
if # right
|
if # right
|
||||||
|
@ -518,7 +484,7 @@ short
|
||||||
# let's return
|
# let's return
|
||||||
return Node(
|
return Node(
|
||||||
syms.simple_stmt,
|
syms.simple_stmt,
|
||||||
[Node(statement, result), Leaf(token.NEWLINE, '\n')], # FIXME: \r\n?
|
[Node(statement, result), Leaf(token.NEWLINE, "\n")], # FIXME: \r\n?
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -105,20 +105,7 @@ def g():
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -3,9 +3,9 @@
|
@@ -25,23 +25,30 @@
|
||||||
|
|
||||||
# leading comment
|
|
||||||
def f():
|
|
||||||
- NO = ""
|
|
||||||
- SPACE = " "
|
|
||||||
- DOUBLESPACE = " "
|
|
||||||
+ NO = ''
|
|
||||||
+ SPACE = ' '
|
|
||||||
+ DOUBLESPACE = ' '
|
|
||||||
|
|
||||||
t = leaf.type
|
|
||||||
p = leaf.parent # trailing comment
|
|
||||||
@@ -25,35 +25,41 @@
|
|
||||||
return NO
|
return NO
|
||||||
|
|
||||||
if prevp.type == token.EQUAL:
|
if prevp.type == token.EQUAL:
|
||||||
|
@ -164,21 +151,14 @@ def g():
|
||||||
return NO
|
return NO
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
@@ -49,7 +56,6 @@
|
||||||
# SECTION BECAUSE SECTIONS
|
# SECTION BECAUSE SECTIONS
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
-
|
-
|
||||||
|
|
||||||
def g():
|
def g():
|
||||||
- NO = ""
|
NO = ""
|
||||||
- SPACE = " "
|
SPACE = " "
|
||||||
- DOUBLESPACE = " "
|
|
||||||
+ NO = ''
|
|
||||||
+ SPACE = ' '
|
|
||||||
+ DOUBLESPACE = ' '
|
|
||||||
|
|
||||||
t = leaf.type
|
|
||||||
p = leaf.parent
|
|
||||||
@@ -67,7 +73,7 @@
|
@@ -67,7 +73,7 @@
|
||||||
return DOUBLESPACE
|
return DOUBLESPACE
|
||||||
|
|
||||||
|
@ -221,9 +201,9 @@ def g():
|
||||||
|
|
||||||
# leading comment
|
# leading comment
|
||||||
def f():
|
def f():
|
||||||
NO = ''
|
NO = ""
|
||||||
SPACE = ' '
|
SPACE = " "
|
||||||
DOUBLESPACE = ' '
|
DOUBLESPACE = " "
|
||||||
|
|
||||||
t = leaf.type
|
t = leaf.type
|
||||||
p = leaf.parent # trailing comment
|
p = leaf.parent # trailing comment
|
||||||
|
@ -275,9 +255,9 @@ def f():
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
def g():
|
def g():
|
||||||
NO = ''
|
NO = ""
|
||||||
SPACE = ' '
|
SPACE = " "
|
||||||
DOUBLESPACE = ' '
|
DOUBLESPACE = " "
|
||||||
|
|
||||||
t = leaf.type
|
t = leaf.type
|
||||||
p = leaf.parent
|
p = leaf.parent
|
||||||
|
|
|
@ -268,22 +268,16 @@ last_call()
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -1,5 +1,6 @@
|
@@ -1,5 +1,6 @@
|
||||||
-"some_string"
|
|
||||||
-b"\\xa3"
|
|
||||||
+...
|
+...
|
||||||
+'some_string'
|
"some_string"
|
||||||
|
-b"\\xa3"
|
||||||
+b'\\xa3'
|
+b'\\xa3'
|
||||||
Name
|
Name
|
||||||
None
|
None
|
||||||
True
|
True
|
||||||
@@ -35,10 +36,11 @@
|
@@ -38,7 +39,8 @@
|
||||||
lambda arg: None
|
lambda a, b, c=True, *, d=(1 << v2), e="str": a
|
||||||
lambda a=True: a
|
lambda a, b, c=True, *vararg, d=(v1 << 2), e="str", **kwargs: a + b
|
||||||
lambda a, b, c=True: a
|
|
||||||
-lambda a, b, c=True, *, d=(1 << v2), e="str": a
|
|
||||||
-lambda a, b, c=True, *vararg, d=(v1 << 2), e="str", **kwargs: a + b
|
|
||||||
+lambda a, b, c=True, *, d=(1 << v2), e='str': a
|
|
||||||
+lambda a, b, c=True, *vararg, d=(v1 << 2), e='str', **kwargs: a + b
|
|
||||||
manylambdas = lambda x=lambda y=lambda z=1: z: y(): x()
|
manylambdas = lambda x=lambda y=lambda z=1: z: y(): x()
|
||||||
-foo = lambda port_id, ignore_missing: {
|
-foo = lambda port_id, ignore_missing: {
|
||||||
+foo = lambda port_id,
|
+foo = lambda port_id,
|
||||||
|
@ -291,38 +285,16 @@ last_call()
|
||||||
"port1": port1_resource,
|
"port1": port1_resource,
|
||||||
"port2": port2_resource,
|
"port2": port2_resource,
|
||||||
}[port_id]
|
}[port_id]
|
||||||
@@ -52,11 +54,11 @@
|
@@ -56,7 +58,7 @@
|
||||||
if (1 if super_long_test_name else 2)
|
{"2.7": dead, "3.7": (long_live or die_hard), **{"3.6": verygood}}
|
||||||
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), **{"3.6": verygood}}
|
|
||||||
+{'2.7': dead, '3.7': (long_live or die_hard)}
|
|
||||||
+{'2.7': dead, '3.7': (long_live or die_hard), **{'3.6': verygood}}
|
|
||||||
{**a, **b, **c}
|
{**a, **b, **c}
|
||||||
-{"2.7", "3.6", "3.7", "3.8", "3.9", ("4.0" if gilectomy else "3.10")}
|
{"2.7", "3.6", "3.7", "3.8", "3.9", ("4.0" if gilectomy else "3.10")}
|
||||||
-({"a": "b"}, (True or False), (+value), "string", b"bytes") or None
|
-({"a": "b"}, (True or False), (+value), "string", b"bytes") or None
|
||||||
+{'2.7', '3.6', '3.7', '3.8', '3.9', ('4.0' if gilectomy else '3.10')}
|
+({"a": "b"}, (True or False), (+value), "string", b'bytes') or None
|
||||||
+({'a': 'b'}, (True or False), (+value), 'string', b'bytes') or None
|
|
||||||
()
|
()
|
||||||
(1,)
|
(1,)
|
||||||
(1, 2)
|
(1, 2)
|
||||||
@@ -88,32 +90,33 @@
|
@@ -100,7 +102,8 @@
|
||||||
]
|
|
||||||
{i for i in (1, 2, 3)}
|
|
||||||
{(i**2) for i in (1, 2, 3)}
|
|
||||||
-{(i**2) for i, _ in ((1, "a"), (2, "b"), (3, "c"))}
|
|
||||||
+{(i**2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}
|
|
||||||
{((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3)}
|
|
||||||
[i for i in (1, 2, 3)]
|
|
||||||
[(i**2) for i in (1, 2, 3)]
|
|
||||||
-[(i**2) for i, _ in ((1, "a"), (2, "b"), (3, "c"))]
|
|
||||||
+[(i**2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]
|
|
||||||
[((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3)]
|
|
||||||
{i: 0 for i in (1, 2, 3)}
|
|
||||||
-{i: j for i, j in ((1, "a"), (2, "b"), (3, "c"))}
|
|
||||||
+{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}
|
|
||||||
{a: b * 2 for a, b in dictionary.items()}
|
|
||||||
{a: b * -2 for a, b in dictionary.items()}
|
{a: b * -2 for a, b in dictionary.items()}
|
||||||
{
|
{
|
||||||
k: v
|
k: v
|
||||||
|
@ -332,23 +304,6 @@ last_call()
|
||||||
}
|
}
|
||||||
Python3 > Python2 > COBOL
|
Python3 > Python2 > COBOL
|
||||||
Life is Life
|
Life is Life
|
||||||
call()
|
|
||||||
call(arg)
|
|
||||||
-call(kwarg="hey")
|
|
||||||
-call(arg, kwarg="hey")
|
|
||||||
-call(arg, another, kwarg="hey", **kwargs)
|
|
||||||
+call(kwarg='hey')
|
|
||||||
+call(arg, kwarg='hey')
|
|
||||||
+call(arg, another, kwarg='hey', **kwargs)
|
|
||||||
call(
|
|
||||||
this_is_a_very_long_variable_which_will_force_a_delimiter_split,
|
|
||||||
arg,
|
|
||||||
another,
|
|
||||||
- kwarg="hey",
|
|
||||||
+ kwarg='hey',
|
|
||||||
**kwargs,
|
|
||||||
) # note: no trailing comma pre-3.6
|
|
||||||
call(*gidgets[:2])
|
|
||||||
@@ -122,8 +125,8 @@
|
@@ -122,8 +125,8 @@
|
||||||
call(b, **self.screen_kwargs)
|
call(b, **self.screen_kwargs)
|
||||||
lukasz.langa.pl
|
lukasz.langa.pl
|
||||||
|
@ -367,19 +322,19 @@ last_call()
|
||||||
-xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod( # type: ignore
|
-xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod( # type: ignore
|
||||||
- sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)
|
- sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)
|
||||||
+xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = (
|
+xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = (
|
||||||
|
+ classmethod(sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)) # type: ignore
|
||||||
|
+)
|
||||||
|
+xxxx_xxx_xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = (
|
||||||
+ classmethod(sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)) # type: ignore
|
+ classmethod(sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)) # type: ignore
|
||||||
)
|
)
|
||||||
-xxxx_xxx_xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod( # type: ignore
|
-xxxx_xxx_xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod( # type: ignore
|
||||||
- sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)
|
- sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)
|
||||||
+xxxx_xxx_xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = (
|
+xxxx_xxx_xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = (
|
||||||
+ classmethod(sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)) # type: ignore
|
+ classmethod(sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__))
|
||||||
)
|
)
|
||||||
-xxxx_xxx_xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod(
|
-xxxx_xxx_xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod(
|
||||||
- sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)
|
- sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)
|
||||||
-) # type: ignore
|
-) # type: ignore
|
||||||
+xxxx_xxx_xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = (
|
|
||||||
+ classmethod(sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__))
|
|
||||||
+)
|
|
||||||
slice[0]
|
slice[0]
|
||||||
slice[0:1]
|
slice[0:1]
|
||||||
slice[0:1:2]
|
slice[0:1:2]
|
||||||
|
@ -405,46 +360,25 @@ last_call()
|
||||||
numpy[:, (0, 1, 2, 5)]
|
numpy[:, (0, 1, 2, 5)]
|
||||||
numpy[0, [0]]
|
numpy[0, [0]]
|
||||||
numpy[:, [i]]
|
numpy[:, [i]]
|
||||||
@@ -172,17 +175,17 @@
|
@@ -172,7 +175,7 @@
|
||||||
numpy[-(c + 1) :, d]
|
numpy[-(c + 1) :, d]
|
||||||
numpy[:, l[-2]]
|
numpy[:, l[-2]]
|
||||||
numpy[:, ::-1]
|
numpy[:, ::-1]
|
||||||
-numpy[np.newaxis, :]
|
-numpy[np.newaxis, :]
|
||||||
+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}
|
||||||
-{"2.7", "3.6", "3.7", "3.8", "3.9", "4.0" if gilectomy else "3.10"}
|
{"2.7", "3.6", "3.7", "3.8", "3.9", "4.0" if gilectomy else "3.10"}
|
||||||
+{'2.7': dead, '3.7': long_live or die_hard}
|
|
||||||
+{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}
|
|
||||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]
|
|
||||||
(SomeName)
|
|
||||||
SomeName
|
|
||||||
(Good, Bad, Ugly)
|
|
||||||
(i for i in (1, 2, 3))
|
|
||||||
((i**2) for i in (1, 2, 3))
|
|
||||||
-((i**2) for i, _ in ((1, "a"), (2, "b"), (3, "c")))
|
|
||||||
+((i**2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))
|
|
||||||
(((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3))
|
|
||||||
(*starred,)
|
|
||||||
{
|
|
||||||
@@ -201,30 +204,26 @@
|
@@ -201,30 +204,26 @@
|
||||||
e = (1,).count(1)
|
e = (1,).count(1)
|
||||||
f = 1, *range(10)
|
f = 1, *range(10)
|
||||||
g = 1, *"ten"
|
g = 1, *"ten"
|
||||||
-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(
|
||||||
- vars_to_remove
|
- vars_to_remove
|
||||||
+what_is_up_with_those_new_coord_names = (
|
-)
|
||||||
+ (coord_names
|
|
||||||
+ + set(vars_to_create))
|
|
||||||
+ + set(vars_to_remove)
|
|
||||||
)
|
|
||||||
-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(
|
||||||
- vars_to_remove
|
- vars_to_remove
|
||||||
+what_is_up_with_those_new_coord_names = (
|
-)
|
||||||
+ (coord_names
|
|
||||||
+ | set(vars_to_create))
|
|
||||||
+ - set(vars_to_remove)
|
|
||||||
)
|
|
||||||
-result = (
|
-result = (
|
||||||
- session.query(models.Customer.id)
|
- session.query(models.Customer.id)
|
||||||
- .filter(
|
- .filter(
|
||||||
|
@ -452,7 +386,11 @@ last_call()
|
||||||
- )
|
- )
|
||||||
- .order_by(models.Customer.id.asc())
|
- .order_by(models.Customer.id.asc())
|
||||||
- .all()
|
- .all()
|
||||||
-)
|
+what_is_up_with_those_new_coord_names = (
|
||||||
|
+ (coord_names
|
||||||
|
+ + set(vars_to_create))
|
||||||
|
+ + set(vars_to_remove)
|
||||||
|
)
|
||||||
-result = (
|
-result = (
|
||||||
- session.query(models.Customer.id)
|
- session.query(models.Customer.id)
|
||||||
- .filter(
|
- .filter(
|
||||||
|
@ -462,7 +400,11 @@ last_call()
|
||||||
- models.Customer.id.asc(),
|
- models.Customer.id.asc(),
|
||||||
- )
|
- )
|
||||||
- .all()
|
- .all()
|
||||||
-)
|
+what_is_up_with_those_new_coord_names = (
|
||||||
|
+ (coord_names
|
||||||
|
+ | set(vars_to_create))
|
||||||
|
+ - set(vars_to_remove)
|
||||||
|
)
|
||||||
+result = session.query(models.Customer.id).filter(
|
+result = session.query(models.Customer.id).filter(
|
||||||
+ models.Customer.account_id == account_id,
|
+ models.Customer.account_id == account_id,
|
||||||
+ models.Customer.email == email_address,
|
+ models.Customer.email == email_address,
|
||||||
|
@ -489,15 +431,6 @@ last_call()
|
||||||
assert parens is TooMany
|
assert parens is TooMany
|
||||||
for (x,) in (1,), (2,), (3,):
|
for (x,) in (1,), (2,), (3,):
|
||||||
...
|
...
|
||||||
@@ -272,7 +271,7 @@
|
|
||||||
addr_proto,
|
|
||||||
addr_canonname,
|
|
||||||
addr_sockaddr,
|
|
||||||
-) in socket.getaddrinfo("google.com", "http"):
|
|
||||||
+) in socket.getaddrinfo('google.com', 'http'):
|
|
||||||
pass
|
|
||||||
a = (
|
|
||||||
aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp
|
|
||||||
@@ -327,13 +326,18 @@
|
@@ -327,13 +326,18 @@
|
||||||
):
|
):
|
||||||
return True
|
return True
|
||||||
|
@ -536,7 +469,7 @@ last_call()
|
||||||
|
|
||||||
```py
|
```py
|
||||||
...
|
...
|
||||||
'some_string'
|
"some_string"
|
||||||
b'\\xa3'
|
b'\\xa3'
|
||||||
Name
|
Name
|
||||||
None
|
None
|
||||||
|
@ -573,8 +506,8 @@ flags & ~select.EPOLLIN and waiters.write_task is not None
|
||||||
lambda arg: None
|
lambda arg: None
|
||||||
lambda a=True: a
|
lambda a=True: a
|
||||||
lambda a, b, c=True: a
|
lambda a, b, c=True: a
|
||||||
lambda a, b, c=True, *, d=(1 << v2), e='str': a
|
lambda a, b, c=True, *, d=(1 << v2), e="str": a
|
||||||
lambda a, b, c=True, *vararg, d=(v1 << 2), e='str', **kwargs: a + b
|
lambda a, b, c=True, *vararg, d=(v1 << 2), e="str", **kwargs: a + b
|
||||||
manylambdas = lambda x=lambda y=lambda z=1: z: y(): x()
|
manylambdas = lambda x=lambda y=lambda z=1: z: y(): x()
|
||||||
foo = lambda port_id,
|
foo = lambda port_id,
|
||||||
ignore_missing,: {
|
ignore_missing,: {
|
||||||
|
@ -591,11 +524,11 @@ str or None if (1 if True else 2) else str or bytes or None
|
||||||
if (1 if super_long_test_name else 2)
|
if (1 if super_long_test_name else 2)
|
||||||
else (str or bytes or None)
|
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)}
|
||||||
{'2.7': dead, '3.7': (long_live or die_hard), **{'3.6': verygood}}
|
{"2.7": dead, "3.7": (long_live or die_hard), **{"3.6": verygood}}
|
||||||
{**a, **b, **c}
|
{**a, **b, **c}
|
||||||
{'2.7', '3.6', '3.7', '3.8', '3.9', ('4.0' if gilectomy else '3.10')}
|
{"2.7", "3.6", "3.7", "3.8", "3.9", ("4.0" if gilectomy else "3.10")}
|
||||||
({'a': 'b'}, (True or False), (+value), 'string', b'bytes') or None
|
({"a": "b"}, (True or False), (+value), "string", b'bytes') or None
|
||||||
()
|
()
|
||||||
(1,)
|
(1,)
|
||||||
(1, 2)
|
(1, 2)
|
||||||
|
@ -627,14 +560,14 @@ str or None if (1 if True else 2) else str or bytes or None
|
||||||
]
|
]
|
||||||
{i for i in (1, 2, 3)}
|
{i for i in (1, 2, 3)}
|
||||||
{(i**2) for i in (1, 2, 3)}
|
{(i**2) for i in (1, 2, 3)}
|
||||||
{(i**2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}
|
{(i**2) for i, _ in ((1, "a"), (2, "b"), (3, "c"))}
|
||||||
{((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3)}
|
{((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3)}
|
||||||
[i for i in (1, 2, 3)]
|
[i for i in (1, 2, 3)]
|
||||||
[(i**2) for i in (1, 2, 3)]
|
[(i**2) for i in (1, 2, 3)]
|
||||||
[(i**2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]
|
[(i**2) for i, _ in ((1, "a"), (2, "b"), (3, "c"))]
|
||||||
[((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3)]
|
[((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3)]
|
||||||
{i: 0 for i in (1, 2, 3)}
|
{i: 0 for i in (1, 2, 3)}
|
||||||
{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}
|
{i: j for i, j in ((1, "a"), (2, "b"), (3, "c"))}
|
||||||
{a: b * 2 for a, b in dictionary.items()}
|
{a: b * 2 for a, b in dictionary.items()}
|
||||||
{a: b * -2 for a, b in dictionary.items()}
|
{a: b * -2 for a, b in dictionary.items()}
|
||||||
{
|
{
|
||||||
|
@ -646,14 +579,14 @@ Python3 > Python2 > COBOL
|
||||||
Life is Life
|
Life is Life
|
||||||
call()
|
call()
|
||||||
call(arg)
|
call(arg)
|
||||||
call(kwarg='hey')
|
call(kwarg="hey")
|
||||||
call(arg, kwarg='hey')
|
call(arg, kwarg="hey")
|
||||||
call(arg, another, kwarg='hey', **kwargs)
|
call(arg, another, kwarg="hey", **kwargs)
|
||||||
call(
|
call(
|
||||||
this_is_a_very_long_variable_which_will_force_a_delimiter_split,
|
this_is_a_very_long_variable_which_will_force_a_delimiter_split,
|
||||||
arg,
|
arg,
|
||||||
another,
|
another,
|
||||||
kwarg='hey',
|
kwarg="hey",
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) # note: no trailing comma pre-3.6
|
) # note: no trailing comma pre-3.6
|
||||||
call(*gidgets[:2])
|
call(*gidgets[:2])
|
||||||
|
@ -714,15 +647,15 @@ 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}
|
||||||
{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}
|
{"2.7", "3.6", "3.7", "3.8", "3.9", "4.0" if gilectomy else "3.10"}
|
||||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]
|
||||||
(SomeName)
|
(SomeName)
|
||||||
SomeName
|
SomeName
|
||||||
(Good, Bad, Ugly)
|
(Good, Bad, Ugly)
|
||||||
(i for i in (1, 2, 3))
|
(i for i in (1, 2, 3))
|
||||||
((i**2) for i in (1, 2, 3))
|
((i**2) for i in (1, 2, 3))
|
||||||
((i**2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))
|
((i**2) for i, _ in ((1, "a"), (2, "b"), (3, "c")))
|
||||||
(((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3))
|
(((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3))
|
||||||
(*starred,)
|
(*starred,)
|
||||||
{
|
{
|
||||||
|
@ -808,7 +741,7 @@ for (
|
||||||
addr_proto,
|
addr_proto,
|
||||||
addr_canonname,
|
addr_canonname,
|
||||||
addr_sockaddr,
|
addr_sockaddr,
|
||||||
) in socket.getaddrinfo('google.com', 'http'):
|
) in socket.getaddrinfo("google.com", "http"):
|
||||||
pass
|
pass
|
||||||
a = (
|
a = (
|
||||||
aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp
|
aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp
|
||||||
|
|
|
@ -67,11 +67,11 @@ def test_calculate_fades():
|
||||||
-
|
-
|
||||||
- # Test don't manage the volume
|
- # Test don't manage the volume
|
||||||
+@pytest.mark.parametrize(
|
+@pytest.mark.parametrize(
|
||||||
+ 'test',
|
+ "test",
|
||||||
[
|
[
|
||||||
- ('stuff', 'in')
|
- ('stuff', 'in')
|
||||||
+ # Test don't manage the volume
|
+ # Test don't manage the volume
|
||||||
+ [('stuff', 'in')],
|
+ [("stuff", "in")],
|
||||||
],
|
],
|
||||||
-])
|
-])
|
||||||
+)
|
+)
|
||||||
|
@ -123,10 +123,10 @@ TmEx = 2
|
||||||
# Position, Volume, State, TmSt/TmEx/None, [call, [arg1...]]
|
# Position, Volume, State, TmSt/TmEx/None, [call, [arg1...]]
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'test',
|
"test",
|
||||||
[
|
[
|
||||||
# Test don't manage the volume
|
# Test don't manage the volume
|
||||||
[('stuff', 'in')],
|
[("stuff", "in")],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_fader(test):
|
def test_fader(test):
|
||||||
|
|
|
@ -97,17 +97,20 @@ elif unformatted:
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -5,8 +5,7 @@
|
@@ -3,10 +3,8 @@
|
||||||
|
entry_points={
|
||||||
|
# fmt: off
|
||||||
"console_scripts": [
|
"console_scripts": [
|
||||||
"foo-bar"
|
- "foo-bar"
|
||||||
"=foo.bar.:main",
|
- "=foo.bar.:main",
|
||||||
- # fmt: on
|
- # fmt: on
|
||||||
- ] # Includes an formatted indentation.
|
- ] # Includes an formatted indentation.
|
||||||
|
+ "foo-bar" "=foo.bar.:main",
|
||||||
+ ],
|
+ ],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,8 +17,8 @@
|
@@ -18,8 +16,8 @@
|
||||||
"ls",
|
"ls",
|
||||||
"-la",
|
"-la",
|
||||||
]
|
]
|
||||||
|
@ -118,7 +121,7 @@ elif unformatted:
|
||||||
check=True,
|
check=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -27,9 +26,8 @@
|
@@ -27,9 +25,8 @@
|
||||||
# Regression test for https://github.com/psf/black/issues/3026.
|
# Regression test for https://github.com/psf/black/issues/3026.
|
||||||
def test_func():
|
def test_func():
|
||||||
# yapf: disable
|
# yapf: disable
|
||||||
|
@ -129,7 +132,7 @@ elif unformatted:
|
||||||
elif b:
|
elif b:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -39,10 +37,10 @@
|
@@ -39,10 +36,10 @@
|
||||||
# Regression test for https://github.com/psf/black/issues/2567.
|
# Regression test for https://github.com/psf/black/issues/2567.
|
||||||
if True:
|
if True:
|
||||||
# fmt: off
|
# fmt: off
|
||||||
|
@ -144,7 +147,7 @@ elif unformatted:
|
||||||
else:
|
else:
|
||||||
print("This will be formatted")
|
print("This will be formatted")
|
||||||
|
|
||||||
@@ -52,14 +50,11 @@
|
@@ -52,14 +49,11 @@
|
||||||
async def call(param):
|
async def call(param):
|
||||||
if param:
|
if param:
|
||||||
# fmt: off
|
# fmt: off
|
||||||
|
@ -162,7 +165,7 @@ elif unformatted:
|
||||||
|
|
||||||
print("This will be formatted")
|
print("This will be formatted")
|
||||||
|
|
||||||
@@ -68,20 +63,21 @@
|
@@ -68,20 +62,21 @@
|
||||||
class Named(t.Protocol):
|
class Named(t.Protocol):
|
||||||
# fmt: off
|
# fmt: off
|
||||||
@property
|
@property
|
||||||
|
@ -198,8 +201,7 @@ setup(
|
||||||
entry_points={
|
entry_points={
|
||||||
# fmt: off
|
# fmt: off
|
||||||
"console_scripts": [
|
"console_scripts": [
|
||||||
"foo-bar"
|
"foo-bar" "=foo.bar.:main",
|
||||||
"=foo.bar.:main",
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -117,32 +117,7 @@ def __await__(): return (yield)
|
||||||
|
|
||||||
|
|
||||||
def func_no_args():
|
def func_no_args():
|
||||||
@@ -27,7 +27,7 @@
|
@@ -64,19 +64,14 @@
|
||||||
async def coroutine(arg, exec=False):
|
|
||||||
"Single-line docstring. Multiline is harder to reformat."
|
|
||||||
async with some_connection() as conn:
|
|
||||||
- await conn.do_what_i_mean("SELECT bobby, tables FROM xkcd", timeout=2)
|
|
||||||
+ await conn.do_what_i_mean('SELECT bobby, tables FROM xkcd', timeout=2)
|
|
||||||
await asyncio.sleep(1)
|
|
||||||
|
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@
|
|
||||||
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)))
|
|
||||||
assert task._cancel_stack[: len(old_stack)] == old_stack
|
|
||||||
|
|
||||||
@@ -58,25 +58,20 @@
|
|
||||||
f: int = -1,
|
|
||||||
g: int = 1 if False else 2,
|
|
||||||
h: str = "",
|
|
||||||
- i: str = r"",
|
|
||||||
+ i: str = r'',
|
|
||||||
):
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
def spaces2(result=_core.Value(None)):
|
def spaces2(result=_core.Value(None)):
|
||||||
|
@ -218,7 +193,7 @@ def func_no_args():
|
||||||
async def coroutine(arg, exec=False):
|
async def coroutine(arg, exec=False):
|
||||||
"Single-line docstring. Multiline is harder to reformat."
|
"Single-line docstring. Multiline is harder to reformat."
|
||||||
async with some_connection() as conn:
|
async with some_connection() as conn:
|
||||||
await conn.do_what_i_mean('SELECT bobby, tables FROM xkcd', timeout=2)
|
await conn.do_what_i_mean("SELECT bobby, tables FROM xkcd", timeout=2)
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
|
@ -235,7 +210,7 @@ def function_signature_stress_test(
|
||||||
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
|
||||||
|
|
||||||
|
@ -249,7 +224,7 @@ def spaces_types(
|
||||||
f: int = -1,
|
f: int = -1,
|
||||||
g: int = 1 if False else 2,
|
g: int = 1 if False else 2,
|
||||||
h: str = "",
|
h: str = "",
|
||||||
i: str = r'',
|
i: str = r"",
|
||||||
):
|
):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
|
@ -74,35 +74,6 @@ some_module.some_function(
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -2,7 +2,7 @@
|
|
||||||
a,
|
|
||||||
):
|
|
||||||
d = {
|
|
||||||
- "key": "value",
|
|
||||||
+ 'key': 'value',
|
|
||||||
}
|
|
||||||
tup = (1,)
|
|
||||||
|
|
||||||
@@ -12,8 +12,8 @@
|
|
||||||
b,
|
|
||||||
):
|
|
||||||
d = {
|
|
||||||
- "key": "value",
|
|
||||||
- "key2": "value2",
|
|
||||||
+ 'key': 'value',
|
|
||||||
+ 'key2': 'value2',
|
|
||||||
}
|
|
||||||
tup = (
|
|
||||||
1,
|
|
||||||
@@ -26,7 +26,7 @@
|
|
||||||
):
|
|
||||||
call(
|
|
||||||
arg={
|
|
||||||
- "explode": "this",
|
|
||||||
+ 'explode': 'this',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
call2(
|
|
||||||
@@ -52,53 +52,52 @@
|
@@ -52,53 +52,52 @@
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -184,7 +155,7 @@ def f(
|
||||||
a,
|
a,
|
||||||
):
|
):
|
||||||
d = {
|
d = {
|
||||||
'key': 'value',
|
"key": "value",
|
||||||
}
|
}
|
||||||
tup = (1,)
|
tup = (1,)
|
||||||
|
|
||||||
|
@ -194,8 +165,8 @@ def f2(
|
||||||
b,
|
b,
|
||||||
):
|
):
|
||||||
d = {
|
d = {
|
||||||
'key': 'value',
|
"key": "value",
|
||||||
'key2': 'value2',
|
"key2": "value2",
|
||||||
}
|
}
|
||||||
tup = (
|
tup = (
|
||||||
1,
|
1,
|
||||||
|
@ -208,7 +179,7 @@ def f(
|
||||||
):
|
):
|
||||||
call(
|
call(
|
||||||
arg={
|
arg={
|
||||||
'explode': 'this',
|
"explode": "this",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
call2(
|
call2(
|
||||||
|
|
|
@ -39,10 +39,9 @@ def docstring_multiline():
|
||||||
name = "Łukasz"
|
name = "Łukasz"
|
||||||
-(f"hello {name}", f"hello {name}")
|
-(f"hello {name}", f"hello {name}")
|
||||||
-(b"", b"")
|
-(b"", b"")
|
||||||
-("", "")
|
|
||||||
+(f"hello {name}", F"hello {name}")
|
+(f"hello {name}", F"hello {name}")
|
||||||
+(b"", B"")
|
+(b"", B"")
|
||||||
+(u"", U"")
|
("", "")
|
||||||
(r"", R"")
|
(r"", R"")
|
||||||
|
|
||||||
-(rf"", rf"", Rf"", Rf"", rf"", rf"", Rf"", Rf"")
|
-(rf"", rf"", Rf"", Rf"", rf"", rf"", Rf"", Rf"")
|
||||||
|
@ -62,7 +61,7 @@ def docstring_multiline():
|
||||||
name = "Łukasz"
|
name = "Łukasz"
|
||||||
(f"hello {name}", F"hello {name}")
|
(f"hello {name}", F"hello {name}")
|
||||||
(b"", B"")
|
(b"", B"")
|
||||||
(u"", U"")
|
("", "")
|
||||||
(r"", R"")
|
(r"", R"")
|
||||||
|
|
||||||
(rf"", fr"", Rf"", fR"", rF"", Fr"", RF"", FR"")
|
(rf"", fr"", Rf"", fR"", rF"", Fr"", RF"", FR"")
|
||||||
|
|
|
@ -38,7 +38,7 @@ class A:
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -1,15 +1,14 @@
|
@@ -1,7 +1,6 @@
|
||||||
-if e1234123412341234.winerror not in (
|
-if e1234123412341234.winerror not in (
|
||||||
- _winapi.ERROR_SEM_TIMEOUT,
|
- _winapi.ERROR_SEM_TIMEOUT,
|
||||||
- _winapi.ERROR_PIPE_BUSY,
|
- _winapi.ERROR_PIPE_BUSY,
|
||||||
|
@ -49,23 +49,13 @@ class A:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if x:
|
if x:
|
||||||
if y:
|
|
||||||
new_id = (
|
|
||||||
max(
|
|
||||||
- Vegetable.objects.order_by("-id")[0].id,
|
|
||||||
- Mineral.objects.order_by("-id")[0].id,
|
|
||||||
+ Vegetable.objects.order_by('-id')[0].id,
|
|
||||||
+ Mineral.objects.order_by('-id')[0].id,
|
|
||||||
)
|
|
||||||
+ 1
|
|
||||||
)
|
|
||||||
@@ -21,14 +20,20 @@
|
@@ -21,14 +20,20 @@
|
||||||
"Your password must contain at least %(min_length)d character.",
|
"Your password must contain at least %(min_length)d character.",
|
||||||
"Your password must contain at least %(min_length)d characters.",
|
"Your password must contain at least %(min_length)d characters.",
|
||||||
self.min_length,
|
self.min_length,
|
||||||
- ) % {"min_length": self.min_length}
|
- ) % {"min_length": self.min_length}
|
||||||
+ )
|
+ )
|
||||||
+ % {'min_length': self.min_length}
|
+ % {"min_length": self.min_length}
|
||||||
|
|
||||||
|
|
||||||
class A:
|
class A:
|
||||||
|
@ -100,8 +90,8 @@ if x:
|
||||||
if y:
|
if y:
|
||||||
new_id = (
|
new_id = (
|
||||||
max(
|
max(
|
||||||
Vegetable.objects.order_by('-id')[0].id,
|
Vegetable.objects.order_by("-id")[0].id,
|
||||||
Mineral.objects.order_by('-id')[0].id,
|
Mineral.objects.order_by("-id")[0].id,
|
||||||
)
|
)
|
||||||
+ 1
|
+ 1
|
||||||
)
|
)
|
||||||
|
@ -114,7 +104,7 @@ class X:
|
||||||
"Your password must contain at least %(min_length)d characters.",
|
"Your password must contain at least %(min_length)d characters.",
|
||||||
self.min_length,
|
self.min_length,
|
||||||
)
|
)
|
||||||
% {'min_length': self.min_length}
|
% {"min_length": self.min_length}
|
||||||
|
|
||||||
|
|
||||||
class A:
|
class A:
|
||||||
|
|
|
@ -23,7 +23,7 @@ if (e123456.get_tk_patchlevel() >= (8, 6, 0, 'final') or
|
||||||
- 8,
|
- 8,
|
||||||
-) <= get_tk_patchlevel() < (8, 6):
|
-) <= get_tk_patchlevel() < (8, 6):
|
||||||
+if (
|
+if (
|
||||||
+ e123456.get_tk_patchlevel() >= (8, 6, 0, 'final')
|
+ e123456.get_tk_patchlevel() >= (8, 6, 0, "final")
|
||||||
+ or (8, 5, 8) <= get_tk_patchlevel() < (8, 6)
|
+ or (8, 5, 8) <= get_tk_patchlevel() < (8, 6)
|
||||||
+):
|
+):
|
||||||
pass
|
pass
|
||||||
|
@ -33,7 +33,7 @@ if (e123456.get_tk_patchlevel() >= (8, 6, 0, 'final') or
|
||||||
|
|
||||||
```py
|
```py
|
||||||
if (
|
if (
|
||||||
e123456.get_tk_patchlevel() >= (8, 6, 0, 'final')
|
e123456.get_tk_patchlevel() >= (8, 6, 0, "final")
|
||||||
or (8, 5, 8) <= get_tk_patchlevel() < (8, 6)
|
or (8, 5, 8) <= get_tk_patchlevel() < (8, 6)
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue