[Python-ideas] Draft2 PEP on string interpolation

Eric V. Smith eric at trueblade.com
Thu Aug 27 21:08:13 CEST 2015


On 08/27/2015 02:30 PM, Andrew Barnert via Python-ideas wrote:
> On Aug 27, 2015, at 10:27, Eric V. Smith <eric at trueblade.com> wrote:
>>
>>> On 08/27/2015 11:22 AM, Mike Miller wrote:
>>>
>>>> On 08/27/2015 06:36 AM, Cody Piersall wrote:
>>>>
>>>> Is the Draft PEP column of the table supposed to have both "Immediate
>>>> Render"
>>>> and "Deferred Render" as "Yes"? I'm hoping that's a typo, otherwise I
>>>> don't
>>>> understand what it means at all.
>>>
>>> Yes, it supports both.  By storing all inputs to the object, it can be
>>> rendered again, with optional changes such as overriding a value, or
>>> escaping the input.
>>
>> The problem with this auto-rendering is that the format_spec and
>> conversion character have to make sense to __format__. For example, you
>> couldn't do this, if value were a string:
>>
>> to_html(e'<p>{value:raw}</p>')
>>
>> Imagine that ":raw" is interpreted by to_html() to mean that the string
>> does not get html escaped.
>>
>> With PEP 501, the format_spec and conversion are opaque to the i-string
>> machinery, and are only interpreted by the custom interpolation function
>> (here, to_html()).
> 
> With str.format, it's the type of value that decides how to interpret the format spec. If you leave it up to the consumer of the i-string (the interpolation function) instead of the value's type, how do you handle things like numeric formats and datetime formats and so on? Would I need to do something like this:
> 
>     to_html(e'<p>{str(e"{value:05}"):raw}</p>')
> 
> Or would to_html (and every other custom interpolator) have to take things like :raw05 and parse out a format spec to pass to value.__format__?

Your interpolator would need to decide. It might never call
value.__format__. It might invent some other protocol, like
__html_escape__(fmt_spec). Or, it might bake-in knowledge of how to
convert whatever types it cares about. Or another good choice would be
to use the singledispatch module. In fact, I like singledispatch so much
that I'm going to have to use it in an example.

> Maybe what you really want is !raw rather than :raw. If there is no conversion, __format__ gets called and the result passed around as part of the i-string object; if there is one, the value, conversion, and format spec get passed instead (and then to_html could decide that conversion 'raw' means to call format(value, format_spec) and then not escape the result). 

You could do that in addition or in place of format_spec. Except
currently conversions are only allowed to be a single character, but I
don't see any reason not to relax that.

The take away is that the PEP 501 i-string machinery applies zero
significance to format_spec and conversion. It just parses them out of
the template string. It's left up to the interpolator to apply some
meaning to them.

> Although that's pretty different from how the standard conversions work (call repr or ascii on the value, then format the resulting string with the format spec). So maybe replacement fields need another subpart separate from both the conversion and the format spec that's only used by custom interpolators?

There's nothing from stopping you from doing this. You could decide that
your format_spec, for some interpolator, is composed of "part1^part2",
and do something based on part1 and part2.

See:
https://bitbucket.org/ericvsmith/istring/src/d92e47c96609eed44ed57b7d3c1932b5a156c01a/istring.py?at=default#istring.py-13
for how my i-string str() interpolator applies format_spec and
conversion. Another interpolator could do something different (for
example,
https://bitbucket.org/ericvsmith/istring/src/d92e47c96609eed44ed57b7d3c1932b5a156c01a/regex.py?at=default#regex.py-6
for regex escaping).

Eric.



More information about the Python-ideas mailing list