Skip to content

Commit

Permalink
Format bytes string (#6166)
Browse files Browse the repository at this point in the history
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

Format bytes string

Closes #6064

## Test Plan

Added a fixture based on string's one
  • Loading branch information
lkh42t authored Jul 31, 2023
1 parent de898c5 commit b95fc6d
Show file tree
Hide file tree
Showing 9 changed files with 577 additions and 89 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"quote_style": "double"
},
{
"quote_style": "single"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
b"' test"
b'" test'

b"\" test"
b'\' test'

# Prefer single quotes for string with more double quotes
b"' \" \" '' \" \" '"

# Prefer double quotes for string with more single quotes
b'\' " " \'\' " " \''

# Prefer double quotes for string with equal amount of single and double quotes
b'" \' " " \'\''
b"' \" '' \" \""

b"\\' \"\""
b'\\\' ""'


b"Test"
B"Test"

rb"Test"
Rb"Test"

b'This string will not include \
backslashes or newline characters.'

if True:
b'This string will not include \
backslashes or newline characters.'

b"""Multiline
String \"
"""

b'''Multiline
String \'
'''

b'''Multiline
String ""
'''

b'''Multiline
String """
'''

b'''Multiline
String "'''

b"""Multiline
String '''
"""

b"""Multiline
String '"""

b'''Multiline
String \"\"\"
'''

# String continuation

b"Let's" b"start" b"with" b"a" b"simple" b"example"

b"Let's" b"start" b"with" b"a" b"simple" b"example" b"now repeat after me:" b"I am confident" b"I am confident" b"I am confident" b"I am confident" b"I am confident"

(
b"Let's" b"start" b"with" b"a" b"simple" b"example" b"now repeat after me:" b"I am confident" b"I am confident" b"I am confident" b"I am confident" b"I am confident"
)

if (
a + b"Let's"
b"start"
b"with"
b"a"
b"simple"
b"example"
b"now repeat after me:"
b"I am confident"
b"I am confident"
b"I am confident"
b"I am confident"
b"I am confident"
):
pass

if b"Let's" b"start" b"with" b"a" b"simple" b"example" b"now repeat after me:" b"I am confident" b"I am confident" b"I am confident" b"I am confident" b"I am confident":
pass

(
# leading
b"a" # trailing part comment

# leading part comment

b"b" # trailing second part comment
# trailing
)

test_particular = [
# squares
b'1.00000000100000000025',
b'1.0000000000000000000000000100000000000000000000000' #...
b'00025',
b'1.0000000000000000000000000000000000000000000010000' #...
b'0000000000000000000000000000000000000000025',
]

# Parenthesized string continuation with messed up indentation
{
"key": (
[],
b'a'
b'b'
b'c'
)
}
11 changes: 4 additions & 7 deletions crates/ruff_python_formatter/src/expression/expr_constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::expression::number::{FormatComplex, FormatFloat, FormatInt};
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses};
use crate::expression::string::{FormatString, StringLayout, StringPrefix, StringQuotes};
use crate::prelude::*;
use crate::{not_yet_implemented_custom_text, FormatNodeRule};
use crate::FormatNodeRule;

#[derive(Default)]
pub struct FormatExprConstant {
Expand Down Expand Up @@ -51,16 +51,13 @@ impl FormatNodeRule<ExprConstant> for FormatExprConstant {
Constant::Int(_) => FormatInt::new(item).fmt(f),
Constant::Float(_) => FormatFloat::new(item).fmt(f),
Constant::Complex { .. } => FormatComplex::new(item).fmt(f),
Constant::Str(_) => {
Constant::Str(_) | Constant::Bytes(_) => {
let string_layout = match self.layout {
ExprConstantLayout::Default => StringLayout::Default,
ExprConstantLayout::String(layout) => layout,
};
FormatString::new(item).with_layout(string_layout).fmt(f)
}
Constant::Bytes(_) => {
not_yet_implemented_custom_text(r#"b"NOT_YET_IMPLEMENTED_BYTE_STRING""#).fmt(f)
}
}
}

Expand All @@ -79,7 +76,7 @@ impl NeedsParentheses for ExprConstant {
_parent: AnyNodeRef,
context: &PyFormatContext,
) -> OptionalParentheses {
if self.value.is_str() {
if self.value.is_str() || self.value.is_bytes() {
let contents = context.locator().slice(self.range());
// Don't wrap triple quoted strings
if is_multiline_string(self, context.source()) || !is_implicit_concatenation(contents) {
Expand All @@ -94,7 +91,7 @@ impl NeedsParentheses for ExprConstant {
}

pub(super) fn is_multiline_string(constant: &ExprConstant, source: &str) -> bool {
if constant.value.is_str() {
if constant.value.is_str() || constant.value.is_bytes() {
let contents = &source[constant.range()];
let prefix = StringPrefix::parse(contents);
let quotes =
Expand Down
4 changes: 2 additions & 2 deletions crates/ruff_python_formatter/src/expression/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub enum StringLayout {

impl<'a> FormatString<'a> {
pub(super) fn new(constant: &'a ExprConstant) -> Self {
debug_assert!(constant.value.is_str());
debug_assert!(constant.value.is_str() || constant.value.is_bytes());
Self {
constant,
layout: StringLayout::Default,
Expand Down Expand Up @@ -70,7 +70,7 @@ struct FormatStringContinuation<'a> {

impl<'a> FormatStringContinuation<'a> {
fn new(constant: &'a ExprConstant) -> Self {
debug_assert!(constant.value.is_str());
debug_assert!(constant.value.is_str() || constant.value.is_bytes());
Self { constant }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,6 @@ instruction()#comment with bad spacing
)
# Please keep __all__ alphabetized within each category.
@@ -45,7 +45,7 @@
# user-defined types and objects
Cheese,
Cheese("Wensleydale"),
- SubBytes(b"spam"),
+ SubBytes(b"NOT_YET_IMPLEMENTED_BYTE_STRING"),
]
if "PYTHON" in os.environ:
@@ -60,8 +60,12 @@
# Comment before function.
def inline_comments_in_brackets_ruin_everything():
Expand Down Expand Up @@ -314,7 +305,7 @@ not_shareables = [
# user-defined types and objects
Cheese,
Cheese("Wensleydale"),
SubBytes(b"NOT_YET_IMPLEMENTED_BYTE_STRING"),
SubBytes(b"spam"),
]
if "PYTHON" in os.environ:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,14 +266,6 @@ last_call()
```diff
--- Black
+++ Ruff
@@ -1,6 +1,6 @@
...
"some_string"
-b"\\xa3"
+b"NOT_YET_IMPLEMENTED_BYTE_STRING"
Name
None
True
@@ -31,7 +31,7 @@
-1
~int and not v1 ^ 123 + v2 | True
Expand All @@ -299,22 +291,7 @@ last_call()
1 if True else 2
str or None if True else str or bytes or None
(str or None) if True else (str or bytes or None)
@@ -57,7 +58,13 @@
{"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"NOT_YET_IMPLEMENTED_BYTE_STRING",
+) or None
()
(1,)
(1, 2)
@@ -115,7 +122,7 @@
@@ -115,7 +116,7 @@
arg,
another,
kwarg="hey",
Expand All @@ -323,19 +300,18 @@ last_call()
) # note: no trailing comma pre-3.6
call(*gidgets[:2])
call(a, *gidgets[:2])
@@ -207,25 +214,15 @@
)
@@ -208,24 +209,14 @@
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(
- models.Customer.account_id == account_id, models.Customer.email == email_address
- )
- .order_by(models.Customer.id.asc())
- .all()
)
-)
-result = (
- session.query(models.Customer.id)
- .filter(
Expand All @@ -357,7 +333,7 @@ last_call()
Ø = set()
authors.łukasz.say_thanks()
mapping = {
@@ -328,13 +325,18 @@
@@ -328,13 +319,18 @@
):
return True
if (
Expand All @@ -379,7 +355,7 @@ last_call()
^ aaaaaaaa.i << aaaaaaaa.k >> aaaaaaaa.l**aaaaaaaa.m // aaaaaaaa.n
):
return True
@@ -342,7 +344,8 @@
@@ -342,7 +338,8 @@
~aaaaaaaaaaaaaaaa.a
+ aaaaaaaaaaaaaaaa.b
- aaaaaaaaaaaaaaaa.c * aaaaaaaaaaaaaaaa.d @ aaaaaaaaaaaaaaaa.e
Expand All @@ -396,7 +372,7 @@ last_call()
```py
...
"some_string"
b"NOT_YET_IMPLEMENTED_BYTE_STRING"
b"\\xa3"
Name
None
True
Expand Down Expand Up @@ -454,13 +430,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"NOT_YET_IMPLEMENTED_BYTE_STRING",
) or None
({"a": "b"}, (True or False), (+value), "string", b"bytes") or None
()
(1,)
(1, 2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,17 @@ def docstring_multiline():
```diff
--- Black
+++ Ruff
@@ -1,13 +1,31 @@
@@ -1,12 +1,21 @@
#!/usr/bin/env python3
name = "Łukasz"
-(f"hello {name}", f"hello {name}")
-(b"", b"")
+(f"NOT_YET_IMPLEMENTED_ExprJoinedStr", f"NOT_YET_IMPLEMENTED_ExprJoinedStr")
+(b"NOT_YET_IMPLEMENTED_BYTE_STRING", b"NOT_YET_IMPLEMENTED_BYTE_STRING")
(b"", b"")
("", "")
(r"", R"")
-(rf"", rf"", Rf"", Rf"", rf"", rf"", Rf"", Rf"")
-(rb"", rb"", Rb"", Rb"", rb"", rb"", Rb"", Rb"")
+(
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
Expand All @@ -55,19 +53,9 @@ def docstring_multiline():
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
+)
+(
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+)
(rb"", rb"", Rb"", Rb"", rb"", rb"", Rb"", Rb"")
def docstring_singleline():
```

## Ruff Output
Expand All @@ -77,7 +65,7 @@ def docstring_multiline():
name = "Łukasz"
(f"NOT_YET_IMPLEMENTED_ExprJoinedStr", f"NOT_YET_IMPLEMENTED_ExprJoinedStr")
(b"NOT_YET_IMPLEMENTED_BYTE_STRING", b"NOT_YET_IMPLEMENTED_BYTE_STRING")
(b"", b"")
("", "")
(r"", R"")
Expand All @@ -91,16 +79,7 @@ name = "Łukasz"
f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
)
(
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
)
(rb"", rb"", Rb"", Rb"", rb"", rb"", Rb"", Rb"")
def docstring_singleline():
Expand Down
Loading

0 comments on commit b95fc6d

Please sign in to comment.