Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Format bytes string #6166

Merged
merged 1 commit into from
Jul 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@konstin I'm a bit surprised that black also normalizes byte strings because I assumed we would need to treat them as opaque bytes. Are you aware of any normalization that isn't safe for byte strings?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as far as i know and reading https://docs.python.org/3/library/stdtypes.html#bytes, byte strings are pretty much like normal strings except that they are limited to ascii input, allow arbitrary bytes and \x behaves differently

}
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