Strong -1

As others noted in prior discussion, even if this existed, it works be an anti-pattern for SQL. So basically, it's just baking in an HTML-only template language into the language syntax.

Python already had excellent HTML templating in libraries. The fact Django has a function with a long name just suggests importing it with a shorter name.

Python has many uses having nothing to do with web pages. This could make sense for PHP (does anyone use that still?). It's a poor for for Python.

On Thu, Jun 10, 2021, 2:31 AM Thomas Güttler <info@thomas-guettler.de> 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

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

Abstract

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

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], 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

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() [2]

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

Template Literals use backticks (like JavaScript Template Literals [3])

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

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.

Alternative Ideas

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

_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@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/