Something I don't understand is whether there is anything about this
proposed feature that can't be accomplished with a simple function.

IIUC, the proposal turns this:

foo = "spam & eggs"
`Here, have some {foo}.`

...into something like this (I am making up a more readable repr):

TemplateLiteral(
    template = " Here, have some {foo}.",
    tokens = (("Here, have some ", True), ("spam & eggs", False)),
)

What is it about this task that cannot be accomplished with a class and
function? Skeleton might look like:

@dataclass
class TemplateLiteral:
    template: str
    tokens: Sequence(Tuple(str, bool)) = field(init = False)

def templify(s: str) -> TemplateLiteral:
    ...

And use it like this:

 >>>  templify("Here, have some {foo}.")
 TemplateLiteral(template = " Here, have some {foo}.", tokens = (("Here,
have some ", True), ("spam & eggs", False)))


What is it about this task that requires it being handled at the language
level...?

---
Ricky.

"I've never met a Kentucky man who wasn't either thinking about going home
or actually going home." - Happy Chandler


On Thu, Jun 10, 2021 at 9:36 AM David Mertz <me...@gnosis.cx> wrote:

> 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 <i...@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
>> <https://github.com/guettli/peps/blob/master/pep-9999.rst>
>>
>> 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 <http:///dev/peps/pep-0012>
>> Created: 08-Jun-2021
>> Python-Version: TODO
>> Post-History: 08-Jun-2021
>> ------------------------------
>>
>> Contents
>>
>>    - Abstract <#m_2818986526677889823_m_-138379983175526697_abstract>
>>    - Motivation <#m_2818986526677889823_m_-138379983175526697_motivation>
>>    - Rationale <#m_2818986526677889823_m_-138379983175526697_rationale>
>>    - Specification
>>    <#m_2818986526677889823_m_-138379983175526697_specification>
>>    - Security Implications
>>    <#m_2818986526677889823_m_-138379983175526697_security-implications>
>>    - Reference Implementation
>>    <#m_2818986526677889823_m_-138379983175526697_reference-implementation>
>>    - Alternative Ideas
>>    <#m_2818986526677889823_m_-138379983175526697_alternative-ideas>
>>    - Rejected Ideas
>>    <#m_2818986526677889823_m_-138379983175526697_rejected-ideas>
>>    - Open Issues
>>    <#m_2818986526677889823_m_-138379983175526697_open-issues>
>>    - References <#m_2818986526677889823_m_-138379983175526697_references>
>>    - Copyright <#m_2818986526677889823_m_-138379983175526697_copyright>
>>
>> Abstract <#m_2818986526677889823_m_-138379983175526697_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 <#m_2818986526677889823_m_-138379983175526697_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]
>> <#m_2818986526677889823_m_-138379983175526697_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 <#m_2818986526677889823_m_-138379983175526697_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] <#m_2818986526677889823_m_-138379983175526697_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 <#m_2818986526677889823_m_-138379983175526697_id9>
>>
>> Template Literals use backticks (like JavaScript Template Literals
>> <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals>
>>  [3] <#m_2818986526677889823_m_-138379983175526697_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 <#m_2818986526677889823_m_-138379983175526697_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
>> <#m_2818986526677889823_m_-138379983175526697_id11>
>>
>> TODO
>> Alternative Ideas <#m_2818986526677889823_m_-138379983175526697_id12>
>>
>> Instead of backticks for example t'...' could be used.
>> Rejected Ideas <#m_2818986526677889823_m_-138379983175526697_id13>
>>
>> TODO
>> Open Issues <#m_2818986526677889823_m_-138379983175526697_id14>
>>
>> TODO
>> References <#m_2818986526677889823_m_-138379983175526697_id15>
>> [1] <#m_2818986526677889823_m_-138379983175526697_id1> FrOW, "HTML
>> Fragments Over the Wire". Frameworks like Unpoly, Hotwire or htmx.
>> [2] <#m_2818986526677889823_m_-138379983175526697_id3>
>> https://docs.djangoproject.com/en/3.2/ref/utils/#django.utils.html.conditional_escape
>> [3] <#m_2818986526677889823_m_-138379983175526697_id5>
>> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
>> Copyright <#m_2818986526677889823_m_-138379983175526697_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/6MMGTZL7VGXXLYL6UZMQ3MRHJW6EA74L/
> 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/XZ22MH2RU643HHYMYYEDOC3F7H22XBBW/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to