mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-23 04:55:09 +00:00
Add support for reformatting byte strings (#3176)
This commit is contained in:
parent
f967f344fc
commit
1e7233a8eb
20 changed files with 90 additions and 59 deletions
|
@ -1,11 +1,12 @@
|
|||
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., `"""`).
|
||||
/// Return the leading quote for a string or byte literal (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) {
|
||||
for pattern in ruff_python::str::TRIPLE_QUOTE_PREFIXES
|
||||
.iter()
|
||||
.chain(ruff_python::bytes::TRIPLE_QUOTE_PREFIXES)
|
||||
.chain(ruff_python::str::SINGLE_QUOTE_PREFIXES)
|
||||
.chain(ruff_python::bytes::SINGLE_QUOTE_PREFIXES)
|
||||
{
|
||||
if first_line.starts_with(pattern) {
|
||||
return Some(pattern);
|
||||
}
|
||||
|
@ -14,10 +15,38 @@ pub fn leading_quote(content: &str) -> Option<&str> {
|
|||
None
|
||||
}
|
||||
|
||||
/// Return the trailing quote string for a docstring (e.g., `"""`).
|
||||
/// Return the trailing quote string for a string or byte literal (e.g., `"""`).
|
||||
pub fn trailing_quote(content: &str) -> Option<&&str> {
|
||||
TRIPLE_QUOTE_SUFFIXES
|
||||
ruff_python::str::TRIPLE_QUOTE_SUFFIXES
|
||||
.iter()
|
||||
.chain(SINGLE_QUOTE_SUFFIXES)
|
||||
.chain(ruff_python::str::SINGLE_QUOTE_SUFFIXES)
|
||||
.find(|&pattern| content.ends_with(pattern))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_prefixes() {
|
||||
let prefixes = ruff_python::str::TRIPLE_QUOTE_PREFIXES
|
||||
.iter()
|
||||
.chain(ruff_python::bytes::TRIPLE_QUOTE_PREFIXES)
|
||||
.chain(ruff_python::str::SINGLE_QUOTE_PREFIXES)
|
||||
.chain(ruff_python::bytes::SINGLE_QUOTE_PREFIXES)
|
||||
.collect::<Vec<_>>();
|
||||
for i in 1..prefixes.len() {
|
||||
for j in 0..i - 1 {
|
||||
if i != j {
|
||||
if prefixes[i].starts_with(prefixes[j]) {
|
||||
assert!(
|
||||
!prefixes[i].starts_with(prefixes[j]),
|
||||
"Prefixes are not unique: {} starts with {}",
|
||||
prefixes[i],
|
||||
prefixes[j]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -652,7 +652,7 @@ fn format_constant(
|
|||
write!(f, [text("False")])?;
|
||||
}
|
||||
}
|
||||
Constant::Str(_) => write!(f, [string_literal(expr)])?,
|
||||
Constant::Str(_) | Constant::Bytes(_) => write!(f, [string_literal(expr)])?,
|
||||
_ => write!(f, [literal(Range::from_located(expr))])?,
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -37,6 +37,7 @@ impl Format<ASTFormatContext<'_>> for StringLiteralPart {
|
|||
}
|
||||
}
|
||||
|
||||
// Retain raw prefixes.
|
||||
let mut is_raw = false;
|
||||
if leading_quote.contains('r') {
|
||||
is_raw = true;
|
||||
|
@ -46,6 +47,11 @@ impl Format<ASTFormatContext<'_>> for StringLiteralPart {
|
|||
f.write_element(FormatElement::StaticText { text: "R" })?;
|
||||
}
|
||||
|
||||
// Normalize bytes literals to use b"...".
|
||||
if leading_quote.contains('b') || leading_quote.contains('B') {
|
||||
f.write_element(FormatElement::StaticText { text: "b" })?;
|
||||
}
|
||||
|
||||
if trailing_quote.len() == 1 {
|
||||
// Single-quoted string.
|
||||
if dquotes == 0 || squotes > 0 {
|
||||
|
|
|
@ -267,14 +267,11 @@ last_call()
|
|||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,5 +1,6 @@
|
||||
@@ -1,3 +1,4 @@
|
||||
+...
|
||||
"some_string"
|
||||
-b"\\xa3"
|
||||
+b'\\xa3'
|
||||
b"\\xa3"
|
||||
Name
|
||||
None
|
||||
True
|
||||
@@ -38,7 +39,8 @@
|
||||
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
|
||||
|
@ -285,15 +282,6 @@ last_call()
|
|||
"port1": port1_resource,
|
||||
"port2": port2_resource,
|
||||
}[port_id]
|
||||
@@ -56,7 +58,7 @@
|
||||
{"2.7": dead, "3.7": (long_live or die_hard), **{"3.6": verygood}}
|
||||
{**a, **b, **c}
|
||||
{"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, 2)
|
||||
@@ -100,7 +102,8 @@
|
||||
{a: b * -2 for a, b in dictionary.items()}
|
||||
{
|
||||
|
@ -470,7 +458,7 @@ last_call()
|
|||
```py
|
||||
...
|
||||
"some_string"
|
||||
b'\\xa3'
|
||||
b"\\xa3"
|
||||
Name
|
||||
None
|
||||
True
|
||||
|
@ -528,7 +516,7 @@ str or None if (1 if True else 2) else str or bytes or None
|
|||
{"2.7": dead, "3.7": (long_live or die_hard), **{"3.6": verygood}}
|
||||
{**a, **b, **c}
|
||||
{"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, 2)
|
||||
|
|
|
@ -33,24 +33,21 @@ def docstring_multiline():
|
|||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,13 +1,13 @@
|
||||
@@ -1,12 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
name = "Łukasz"
|
||||
-(f"hello {name}", f"hello {name}")
|
||||
-(b"", b"")
|
||||
+(f"hello {name}", F"hello {name}")
|
||||
+(b"", B"")
|
||||
(b"", b"")
|
||||
("", "")
|
||||
(r"", R"")
|
||||
|
||||
-(rf"", rf"", Rf"", Rf"", rf"", rf"", Rf"", Rf"")
|
||||
-(rb"", rb"", Rb"", Rb"", rb"", rb"", Rb"", Rb"")
|
||||
+(rf"", fr"", Rf"", fR"", rF"", Fr"", RF"", FR"")
|
||||
+(rb"", br"", Rb"", bR"", rB"", Br"", RB"", BR"")
|
||||
(rb"", rb"", Rb"", Rb"", rb"", rb"", Rb"", Rb"")
|
||||
|
||||
|
||||
def docstring_singleline():
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
|
@ -60,12 +57,12 @@ def docstring_multiline():
|
|||
|
||||
name = "Łukasz"
|
||||
(f"hello {name}", F"hello {name}")
|
||||
(b"", B"")
|
||||
(b"", b"")
|
||||
("", "")
|
||||
(r"", R"")
|
||||
|
||||
(rf"", fr"", Rf"", fR"", rF"", Fr"", RF"", FR"")
|
||||
(rb"", br"", Rb"", bR"", rB"", Br"", RB"", BR"")
|
||||
(rb"", rb"", Rb"", Rb"", rb"", rb"", Rb"", Rb"")
|
||||
|
||||
|
||||
def docstring_singleline():
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue