I am concerned that we have too many string formatting methods:
    % formatting
    .format()
    f-strings
    string templates
(are there others I've missed?).
And now we have another proposed one.
It's all getting a bit much.  And IMO a turnoff for people learning Python (which one should I use, and why?).
Best wishes
Rob Cliffe

On 10/06/2021 07:30, Thomas Güttler wrote:
Thank you Guido, Chris, Matt and Richard for your feedback to my last email.

Here is an updated version called "Template Literals".

I am looking for a core developer who can sponsor this PEP.

Please speak up if you want to help me.

Regards,
  Thomas Güttler

Source and updates: Pre-PEP 9999 <https://github.com/guettli/peps/blob/master/pep-9999.rst>

PEP:    9999
Title:  Template Literals
Author: Thomas Güttler <info at thomas-guettler.de <http://thomas-guettler.de>>
Sponsor:        TODO
Status:         Draft
Type:   Standards Track
Content-Type:   text/x-rst </dev/peps/pep-0012>
Created:        08-Jun-2021
Python-Version:         TODO
Post-History:   08-Jun-2021

------------------------------------------------------------------------

Contents

  * Abstract <#abstract>
  * Motivation <#motivation>
  * Rationale <#rationale>
  * Specification <#specification>
  * Security Implications <#security-implications>
  * Reference Implementation <#reference-implementation>
  * Alternative Ideas <#alternative-ideas>
  * Rejected Ideas <#rejected-ideas>
  * Open Issues <#open-issues>
  * References <#references>
  * Copyright <#copyright>


  Abstract <#id6>

This PEP adds Template Literals to Python.

To avoid code injection like XSS or SQL-injection Template Literals can help you to write save Python code.

Template Literals provide an easy way to access the local and global variables (like f-strings), so that passing a dictionary to the Template is not necessary.


  Motivation <#id7>

In the context of web development Python can do more than providing REST APIs via http. With the trend to Server-Side-Rendering, we face a fundamental question:

How to create HTML with Python?

If you use the FrOW pattern (HTML fragments over the wire) [1] <#frow>, then you will be writing small methods returning small HTML fragments.

As a developer I want to pass escaped data into template literals to be as simple as possible.


  Rationale <#id8>

Imagine you want to create a small HTML fragment in Python, and return it as HTTP-Response:

    HttpResponse(f'''
<h1>Hi {name}</h1>
Your messages: {messages}''')

The problem in above example is, that no escaping gets done.

In above example "name" and "messages" should be treated differently.

The variable "name" should get escaped. For example if the name is "Mary & Bob", the result should be "Mary &amp; Bob".

The variable "messages" contains HTML which is already escaped. It should not be escaped again.

Most frameworks have a way to do this conditional escaping.

For example Django uses conditional_escape() <https://docs.djangoproject.com/en/3.2/ref/utils/#django.utils.html.conditional_escape> [2] <#id2>

With the help of conditional_escape() the above problem could be solved like this:

HttpResponse(f'''
     <h1>Hi {conditional_escape(name)}</h1>
     Your messages: {conditional_escape(messages)}''')

This solution has two drawbacks:

 1. It is too verbose. Typing "conditional_escape(...)" again and
    again is cumbersome.
 2. If a conditional_escape() gets forgotten Cross-site scripting
    attacks could be possible, since malicious users could inject HTML.


  Specification <#id9>

Template Literals use backticks (like JavaScript Template Literals <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals> [3] <#id4>)

Example:

name = 'Mary & Bob'
messages = `<ul><li>message1</li><li>message2</li></ul>`
return HttpResponse(`
     <h1>Hi {name}</h1>
     Your messages: {messages}

     Today: {datetime.date.today()}`)

Expressions within curly braces get handled liked in f-strings (PEP-498).

The Template Literal creates an instance of the new class types.TemplateLiteral.

types.TemplateLiteral has two attributes:

  * template: The raw string inside the backticks.
  * tokens: A list of tuples: (value, is_literal).

For above example this would mean:

template = '''
     <h1>Hi {name}</h1>
     Your messages: {messages}

     Today: {datetime.date.today()}'''

tokens = [
     ('\n        <h1>Hi ', True),
     ('Mary & Bob', False),
     ('</h1>\n        Your messages: ', True),
     (<TemplateLiteral "<ul><li>message1</li><li>message2</li></ul>">, False),
     ('\n\n        Today: ', True),
     (<datetime.date(2021, 6, 9)>, False)
     ]

It is outside this PEP how a consumer of TemplateLiteral handles this data structure.

For example the Django web framework could transform a TemplateLiteral to a SafeString like this:

def template_literal_to_safestring(template_literal):
     return mark_safe(
         ''.join(
             [
                 conditional_escape(value) if not is_literal else value
                 for (value, is_literal) in template_literal.tokens
             ]
         )
     )

This PEP is not related or constraint to the Django framework. It is even not related to HTML. It can be used for any kind of templating.


  Security Implications <#id10>

Template Literals can execute arbitrary code (like f-strings).

Template Literals get created by Python developers, not by users. If you want to make templates available for users (for example if you develop a CMS), then please use a different solution.


  Reference Implementation <#id11>

TODO


  Alternative Ideas <#id12>

Instead of backticks for example t'...' could be used.


  Rejected Ideas <#id13>

TODO


  Open Issues <#id14>

TODO


  References <#id15>

[1] <#id1> FrOW, "HTML Fragments Over the Wire". Frameworks like Unpoly, Hotwire or htmx.

[2] <#id3> https://docs.djangoproject.com/en/3.2/ref/utils/#django.utils.html.conditional_escape <https://docs.djangoproject.com/en/3.2/ref/utils/#django.utils.html.conditional_escape>

[3] <#id5> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals>


  Copyright <#id16>

This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.


_______________________________________________
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/LYAC7JC5253QISKDLRMUCN27GZVIUWZC/
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/7RE5PFETZ7XSFG5VCKP52MKAVQQEMNMT/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to