[Python-ideas] Let’s make escaping in f-literals impossible

Steve Dower steve.dower at python.org
Thu Aug 18 12:50:11 EDT 2016


I'm generally inclined to agree, especially as someone who is very 
likely to be implementing syntax highlighting and completion support 
within f-literals.

I stepped out of the original discussion near the start as it looked 
like we were going to end up with interleaved strings and normal 
expressions, but if that's not the case then it is going to make it very 
difficult to provide a nice coding experience for them.

On 18Aug2016 0805, Philipp A. wrote:
> My poposal is to redo their grammar:
> They shouldn’t be parsed as strings and post-processed, but be their own
> thing. This also opens the door to potentially extend to with something
> like JavaScript’s tagged templates)
>
> Without the limitations of the string tokenization code/rules, only the
> string parts would have escape sequences, and the expression parts would
> be regular python code (“holes” in the literal).

This is where I thought we'd end up - the '{' character (unless escaped 
by, e.g. \N, which addresses a concern below) would terminate the string 
literal and start an expression, which may be followed by a ':' and a 
format code literal. The '}' character would open the next string 
literal, and this continues until the closing quote.

>     They are still strings, there is just post-processing on the string
>     itself to do the interpolation.
>
>
> Sounds hacky to me. I’d rather see a proper parser for them

I believe the proper parser is already used, but the issue is that 
escapes have already been dealt with. Of course, it shouldn't be too 
difficult for the tokenizer to recognize {} quoted expressions within an 
f-literal and not modify escapes. There are multiple ways to handle this.

>     Or another reason is you can explain f-strings as "basically
>     str.format_map(**locals(), **globals()), but without having to make
>     the actual method call" (and worrying about clashing keys but I
>     couldn't think of a way of using dict.update() in a single line).
>     But with your desired change it kills this explanation by saying
>     f-strings aren't like this but some magical string that does all of
>     this stuff before normal string normalization occurs.
>
>
> no, it’s simply the expression parts (that for normal formatting are
> inside of the braces of  .format(...)) are *interleaved* in between
> string parts. they’re not part of the string. just regular plain python
> code.

Agreed. The .format_map() analogy breaks down very quickly when you 
consider f-literals like:

 >>> f'a { \'b\' }'
'a b'

If the contents of the braces were simply keys in the namespace then we 
wouldn't be able to put string literals in there. But because it is an 
arbitrary expression, if we want to put string literals in the f-literal 
(bearing in mind that we may be writing something more like 
f'{x.partition(\'-\')[0]}'), the escaping rules become very messy very 
quickly.

I don't think f'{x.partition('-')[0]}' is any less readable as a result 
of the reused quotes, and it will certainly be easier for highlighters 
to handle (assuming they're doing anything more complicated than simply 
displaying the entire expression in a different colour).

So I too would like to see escapes made unnecessary within the 
expression part of a f-literal. Possibly if we put together a simple 
enough patch for the tokenizer it will be accepted?

Cheers,
Steve



More information about the Python-ideas mailing list