[Python-ideas] String interpolation for all literal strings
Nick Coghlan
ncoghlan at gmail.com
Fri Aug 7 11:50:36 CEST 2015
On 7 August 2015 at 19:03, Nathaniel Smith <njs at pobox.com> wrote:
> On Fri, Aug 7, 2015 at 1:49 AM, Guido van Rossum <guido at python.org> wrote:
>> On Fri, Aug 7, 2015 at 9:33 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:
>>>
>>> We could potentially make f-strings translation friendly by
>>> introducing a bit of indirection into the f-string design: an
>>> __interpolate__ builtin, along the lines of __import__.
>>
>>
>> This seems interesting, but doesn't it require sys._getframe() or similar
>> again? Translations may need to reorder variables. (Or even change the
>> expressions? E.g. to access odd plurals?)
>>
>> The sys._getframe() requirement (if true) would kill this idea thoroughly
>> for me.
>
> AFAICT sys._getframe is unneeded -- I understand Nick's suggestion to
> be that we desugar f"..." to:
>
> __interpolate__("...", locals(), globals())
>
> with the reference to __interpolate__ resolved using the usual lookup
> rules (locals -> globals -> builtins).
Not quite. While I won't be entirely clear on Eric's latest proposal
until the draft PEP is available, my understanding is that an f-string
like:
f"This interpolates \{a} and \{b}"
would currently end up effectively being syntactic sugar for a
formatting operation like:
"This interpolates " + format(a) + " and " + format(b)
While str.format itself probably doesn't provide a good signature for
__interpolate__, the essential information to be passed in to support
lossless translation would be an ordered series of:
* string literals
* (expression_str, value, format_str) substitution triples
Since the fastest string formatting operation we have is actually
still mod-formatting, lets suppose the default implementation of
__interpolate__ was semantically equivalent to:
def __interpolate__(target, expressions, values, format_specs):
return target % tuple(map(format, values, format_specs)
With that definition for default interpolation, the f-string above
would be translated at compile time to the runtime call:
__interpolate__("This interpolates %s and %s", ("a", "b"), (a, b), ("", ""))
All of those except for the __interpolate__ lookup and the (a, b)
tuple would then be stored on the function object as constants.
An opt-in translation interpolator might then look like:
def __interpolate__(target, expressions, values, format_spec):
if not all(expr.isidentifier() for expr in expressions):
raise ValueError("Only variable substitions are permitted
for il8n interpolation")
if any(spec for spec in format_specs):
raise ValueError("Format specifications are not permitted
for il8n interpolation")
catalog_str = target % tuple("${%s}" % expr for expr in expressions)
translated = _(catalog_str)
values = {k:v for k, v in zip(expressions, values)}
return string.Template(translated).safe_substitute()
The string extractor for the il8n library providing that
implementation would also need to know to do the transformation from
f-string formatting to string.Template formatting when generating the
catalog strings
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-ideas
mailing list