JavaScript's tagged template literals do provide nice ergonomics. These
should work well with some variation on PEP
501's types.InterpolationTemplate as the backend implementation. Some
thoughts on what that should look like:

* I also increasingly prefer the idea of using backticks to define such
templates, as opposed to further overloading standard quoting. More below.
* We should separate the static elements of the template from evaluated
expressions. This implies that a tagged template function would have a
signature like def html(template, *exprs). To provide the same user
interface as PEP 501, one could write a tag template function "i" that is
an identity function - thus demonstrating a basic equivalence of these
proposals.
* Literal static strings from the templates are available in both raw and
cooked forms (Unicode escapes applied). So there's no need to add a "r"
prefix for raw.
* Expressions are evaluated immediately using normal scoping and rendered
later (taking into account escaping rules, et). Such rendering can be into
any Python object. So using some "html" tag function would return a DOM
(let's call it HtmlElement in this example) which can be further rendered
eventually into returned text in the scenario of serving HTML.
* Greater likelihood of syntax support. Being able to specify html`<p>Some
expr: {x * y}</p>` probably simplifies being able to provide an IDE
extension that is aware that the html tag function was imported from some
popular library, and can therefore provide assistance with HTML tags or any
other aspects of the templating language used.
* Backticks are multiline and they nest in the context of expressions. This
means there's no need to invent new templating syntax, such as Jinja's {%
for ... %} ... {% endfor %} to provide iteration over a sequence. Just use
Python in the evaluated expressions. So with reference to the example in
the Jinja doc https://jinja.palletsprojects.com/en/3.0.x/templates/#synopsis,
we could have functions like the following that can be further composed to
create larger DOM objects:

def ulistify(id: str, linkage: dict[str, str]) -> HtmlElement:
    # uses a dict to represent the linkage in this example, so slightly
different than the Jinja example
    return html`
<ul id="{id}">{
  html`<li><a href="{href}">{caption}</a></li>` for href, caption in
linkage.items()
}</ul>`

It's possible to write something similar using f-string syntax now, but it
involves careful tracking of which quotes are being used to support
nesting. The interaction of backticks and expression syntax keeps it simple
in comparison.

An example library in the JavaScript ecosystem that builds out from the JS
tagged template literal support is Lit (https://lit.dev/,  note that I
haven't used this library.) Lit provides some nice functionality by
composing HTML DOM out of DOM fragments; and doing this in a lazy fashion
(virtual DOM, as ReactJS demonstrated; I am not aware of a fast virtual DOM
library in Python as a C Extension, but it would seem like a
straightforward thing to write). Anyway, Lit and other similar libraries in
JS could help understand the scope of the available innovation if we were
to add such functionality.

Format specifiers and ! conversions should presumably still be available in
expressions and thus available from the template literal object to be used
as part of any rendering. However, I'm leaving this open for the moment as
to exactly what this looks like - especially if I overlooked any parsing
issues for such support!

Lastly, it's worth noting that types.InterpolationTemplate could look quite
similar to https://262.ecma-international.org/6.0/#sec-tagged-templates if
it's a constant object - a template literal in other words - which a tagged
function is then applied to with the evaluated expressions.

- Jim


On Mon, Jul 5, 2021 at 1:10 AM Thomas Güttler <i...@thomas-guettler.de>
wrote:

>
> Am Fr., 2. Juli 2021 um 12:06 Uhr schrieb Nick Coghlan <ncogh...@gmail.com
> >:
>
>>
>>
>> On Fri, 2 Jul 2021, 5:12 pm Thomas Güttler, <i...@thomas-guettler.de>
>> wrote:
>>
>>> Hi Nick and all other Python ideas friends,
>>>
>>> yes, you are right. There is not much difference between PEP-501 or my
>>> proposal.
>>>
>>> One argument why I would like to prefer backticks:
>>>
>>> Some IDEs detect that you want to use a f-string automatically:
>>>
>>> You type:
>>>
>>> name = 'Peter'
>>> print('Hello {name...
>>>
>>> and the IDE automatically adds the missing "f" in front of the string:
>>>
>>> name = 'Peter'
>>> print(f'Hello {name...
>>>
>>> This is a handy feature (of PyCharm), which would not work reliably if
>>> there are two different prefixes.
>>>
>>> -------
>>>
>>> You mentioned these things:
>>>
>>> eager rendering: I think deferred rendering would increase the
>>> complexity a lot. And I think it is not needed.
>>>
>>
>> Eager rendering is f-strings. Any templating proposal necessarily
>> involves a delayed rendering step, when the template is combined with the
>> interpolated values.
>>
>> runtime value interpolation: It is up to the receiver of
>>> types.InterpolationTemplate to handle the data structure.
>>>
>>
>> I really meant runtime template parsing here (i.e. str.format).
>>
>>
>> dedicated templating libraries: One temp after the other. I think HTML
>>> and SQL libraries would adapt as soon as the foundation
>>> is available.
>>>
>>
>> The existence of i-strings likely wouldn't change the syntax of jinja2
>> templates, Django templates, SQL Alchemy, pandas, etc.
>>
>> I would be happy if PEP-501 would come true.
>>>
>>
>> So would I, but I still don't have a compelling answer to the "but it's
>> yet another subtly different way to do it" objection.
>>
>
>
> Today I read the replies to this thread again.
>
> Of course there where some "-1" replies, but overall there was positive
> feedback.
>
> Today I played with template literals from Javascript:
>
> [image: image.png]
>
> I like it.
>
> Nick, would you be open to adapting to the JS syntax for PEP-501?
>
> I propose `...{var} ...`
>
> This means backticks, but without the dollar sign.
>
> I would make it like in JS: The string in backticks can span several lines.
>
> So what is the next step now?
>
> Regards,
>   Thomas
>
>
> _______________________________________________
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/NRJ7NBRF6KTFWP6SFQLH4FIEK3P2W2AT/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/KEMGEM7JZ4VBZ6PM7QLHO46KADZCMTV5/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to