Repository: psf/black

Issue:
Normalize raw f-strings prefix
**Is your feature request related to a problem? Please describe.**

Black should normalize the prefix used for raw f-strings (https://www.python.org/dev/peps/pep-0498/#raw-f-strings). Both `rf` and `fr` work, but one should be preferred.

Currently, the following code is not changed:

```
    f = rf"hello {world}"
    f = fr"hello {world}"
```

**Describe the solution you'd like**

Pick one and normalize. I don't really care which. `rf` matches the name "raw f-string", but `fr` matches the example in PEP-498 and Jupyterlab syntax highlighting seems to prefer it.

**Describe alternatives you've considered**

Doing nothing leaves open the opportunity for inconsistency and disagreement.

**Additional context**

None



Discussion:
Agree that we should standardize here. This also affects raw bytestrings: `rb'x'` and `br'x'` are both valid.
Just sharing that I  also would like this.

I vote for alphabetical just for a simple standard. `sort()` would just do it then I feel.

```python
fr"foo"
br"foo"
```
Seconded. I weakly prefer `rb"x"` and `fr"x"` visually since they are recognizable pairs to me (rb is a Ruby file extension and fr is a code for French which I can speak some of). But going with the general standard and what tools prefer is definitely better.

edit: or some basic rule like Cooper's one above this comment works too
@cooperlees you mean `br`? :D

```python
>>> bf"foo"
  File "<stdin>", line 1
    bf"foo"
      ^
SyntaxError: invalid syntax
>>> 
```

edit and off-topic: I just realized I can edit anyone's comment now, I guess I could've done that instead lol
> @cooperlees you mean `br`? :D
> 
> ```python
> >>> bf"foo"
>   File "<stdin>", line 1
>     bf"foo"
>       ^
> SyntaxError: invalid syntax
> >>> 
> ```

Sure ...
While having a simple rule is elegant, I think matching spoken word is important like James pointed out. Just to provide one more perspective, I'd prefer:

- `rf` - raw f-string
- `rb` - raw byte string

The simple rule in this case would be "have `r` first", if simplicity is important.
I don't think the alphabetical order convention is a good one, otherwise you might end up with inconsistent placing e.g. `br`, `fr` and `rx` (under the hypothetical scenario where `x` and `rx` are a valid prefixes). I'd prefer either "r-first"---as in "raw f-string/byte string"---or "r-last"---as in the "f" or "b" are the most important parts of the prefix or possibly chain-rule i.e. the "raw" processing is applied before the "format" processing; I don't know how the parser actually handles it.

To me, "r-first"---as in "raw f-string/byte string"---is the clearest justification.
Sorting will also have problems with [the capital-R prefix](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#r-strings-and-r-strings), `Rf""`, `Rb""`, `br""`, `fr""`.  I'd prefer "r-last" (`fR""`, `bR""`) but would be happy with any simple and consistent rule.
@Zac-HD I didn't know about the R-strings. Thanks for that :+1:. Seems odd to have the more common syntax (i.e. lower case r) be for the special case of regular expressions, especially when `br""` doesn't make sense ... I think, but I digress.

I think I agree that `fR""` looks better than `Rf""`. In fact, I'm also moving towards the view that the "best" justification is "r-last" since it is less important than the "f" or "b", even if this isn't as "clear" as "r-first" as in "raw f-string".
To find some common ground first, I think it would be reasonable to propose that no matter which "r/R", the order stays the same. Meaning no mixing `rf` with `fR` and vice versa. And I think allowing other capital letters is a no-go as well. So it seems that the suggestions have converged to:

- `r` first, as in spoken word: `rb"str", rf"str", Rb"str", Rf"str"`
- `r` last, as the common attribute applicable to both `b` and `f`: `br"str", fr"str", bR"str", fR"str"`

Personally I still feel like matching spoken word is more important, and I'm not bothered by the capital "R" being first. That being said arguments can be made both ways. Would the maintainers like to decide, or would we vote, or have a PR race? 😄
We just need to make the call, one way or the other. Maybe ask for more opinions on Discord and then take a majority vote among the maintainers.
I've voted on the poll on Discord, but to explain why I voted for things like `fr` I think it makes more sense for them to be in alphabetical order if they're going to be standardised, as other things' order also follow that pattern
After 8 hours the [poll](https://discord.com/channels/267624335836053506/846434317021741086/846865880742756382) is 8-5 for `rf`. Could the maintainers only vote here thumbs up for `r` first and down for `r` last?

Resolving patch:
diff --git a/src/black/strings.py b/src/black/strings.py
--- a/src/black/strings.py
+++ b/src/black/strings.py
@@ -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():
+        new_prefix = new_prefix[::-1]
     return f"{new_prefix}{match.group(2)}"
 
 
diff --git a/src/blib2to3/pgen2/tokenize.py b/src/blib2to3/pgen2/tokenize.py
--- a/src/blib2to3/pgen2/tokenize.py
+++ b/src/blib2to3/pgen2/tokenize.py
@@ -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:


Test patch:
diff --git a/tests/data/string_prefixes.py b/tests/data/string_prefixes.py
--- a/tests/data/string_prefixes.py
+++ b/tests/data/string_prefixes.py
@@ -1,10 +1,13 @@
-#!/usr/bin/env python3.6
+#!/usr/bin/env python3
 
-name = R"Łukasz"
-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():
@@ -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():