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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normalise string prefix order #2297

Merged
merged 6 commits into from Jan 13, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -28,6 +28,7 @@
`--target-version` is set to 3.10 and higher). (#2728)
- Fix handling of standalone `match()` or `case()` when there is a trailing newline or a
comment inside of the parentheses. (#2760)
- Black now normalizes string prefix order (#2297)

### Packaging

Expand Down
8 changes: 4 additions & 4 deletions docs/the_black_code_style/current_style.md
Expand Up @@ -233,10 +233,10 @@ _Black_ prefers double quotes (`"` and `"""`) over single quotes (`'` and `'''`)
will replace the latter with the former as long as it does not result in more backslash
escapes than before.

_Black_ also standardizes string prefixes, making them always lowercase. On top of that,
if your code is already Python 3.6+ only or it's using the `unicode_literals` future
import, _Black_ will remove `u` from the string prefix as it is meaningless in those
scenarios.
_Black_ also standardizes string prefixes. Prefix characters are made lowercase with the
exception of [capital "R" prefixes](#rstrings-and-rstrings), unicode literal markers
(`u`) are removed because they are meaningless in Python 3, and in the case of multiple
characters "r" is put first as in spoken language: "raw f-string".
Comment on lines +236 to +239
Copy link
Collaborator

Choose a reason for hiding this comment

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

Love this and agree with all!


The main reason to standardize on a single form of quotes is aesthetics. Having one kind
of quotes everywhere reduces reader distraction. It will also enable a future version of
Expand Down
4 changes: 4 additions & 0 deletions src/black/strings.py
Expand Up @@ -149,6 +149,10 @@ def normalize_string_prefix(s: str) -> str:
.replace("U", "")
.replace("u", "")
)

# Python syntax guarantees max 2 prefixes and that one of them is "r"
if len(new_prefix) == 2 and "r" != new_prefix[0].lower():
felix-hilden marked this conversation as resolved.
Show resolved Hide resolved
new_prefix = new_prefix[::-1]
felix-hilden marked this conversation as resolved.
Show resolved Hide resolved
return f"{new_prefix}{match.group(2)}"


Expand Down
2 changes: 1 addition & 1 deletion src/blib2to3/pgen2/tokenize.py
Expand Up @@ -293,7 +293,7 @@ def compat(self, token: Tuple[int, Text], iterable: Iterable[TokenInfo]) -> None


cookie_re = re.compile(r"^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)", re.ASCII)
blank_re = re.compile(br"^[ \t\f]*(?:[#\r\n]|$)", re.ASCII)
blank_re = re.compile(rb"^[ \t\f]*(?:[#\r\n]|$)", re.ASCII)


def _get_normal_name(orig_enc: str) -> str:
Expand Down
30 changes: 18 additions & 12 deletions tests/data/string_prefixes.py
@@ -1,10 +1,13 @@
#!/usr/bin/env python3.6
#!/usr/bin/env python3

name = R"艁ukasz"
felix-hilden marked this conversation as resolved.
Show resolved Hide resolved
F"hello {name}"
B"hello"
r"hello"
fR"hello"
name = "艁ukasz"
(f"hello {name}", F"hello {name}")
(b"", B"")
(u"", U"")
(r"", R"")

(rf"", fr"", Rf"", fR"", rF"", Fr"", RF"", FR"")
(rb"", br"", Rb"", bR"", rB"", Br"", RB"", BR"")


def docstring_singleline():
Expand All @@ -20,13 +23,16 @@ def docstring_multiline():
# output


#!/usr/bin/env python3.6
#!/usr/bin/env python3

name = "艁ukasz"
(f"hello {name}", f"hello {name}")
(b"", b"")
("", "")
(r"", R"")

name = R"艁ukasz"
f"hello {name}"
b"hello"
r"hello"
fR"hello"
(rf"", rf"", Rf"", Rf"", rf"", rf"", Rf"", Rf"")
(rb"", rb"", Rb"", Rb"", rb"", rb"", Rb"", Rb"")


def docstring_singleline():
Expand Down