| |
| ▲ | davepeck 9 days ago | parent [-] | | > Agreed, although this doesn't work as well for HTML or SQL that doesn't fit on one line. PEP 750 t-strings literals work with python's tripe-quote syntax (and its lesser-used implicit string concat syntax): lots_of_html = t"""
<div>
<main>
<h1>Hello</h1>
</main>
</div>
"""
My hope is that we'll quickly see the tooling ecosystem catch up and -- just like in JavaScript-land -- support syntax coloring and formatting specific types of content in t-strings, like HTML. | | |
| ▲ | neilv 9 days ago | parent | next [-] | | Yeah, editor support will help a lot. Though the PEP's way of doing things doesn't specify the language of the template where the literal occurs, so detection of that might have to be kludged. (Or, in a sufficiently working program, an editor with semantic analysis access could use something like type inference in the Python side, to determine the language in a less-kludgey way.) | | |
| ▲ | davepeck 9 days ago | parent [-] | | > doesn't specify the language of the template where the literal occurs Yeah, something we spent a bunch of time considering. In the end, we decided it probably needed to stay out of scope for the PEP. You're right that JavaScript has an easier time here. Most of the JS tools we looked at simply inspect the name of the tag and if it's (say) html, they attempt to color/format string content as HTML regardless of what the html() function actually does or the string's contents. Currently, tools like black have no knowledge of types. I'm guessing some amount of kludging is to be expected on day one. But my hope is over the long term, we'll see a story emerge for how annotations can indicate the expected content type. |
| |
| ▲ | kazinator 9 days ago | parent | prev [-] | | But that will not apply proper HTML escaping to the evil script element, allowing injection, and allows tags not to be closed: lots_of_html = t"""
<div>
<main>
<p>{evil}>/p>
<main>
</span>
"""
| | |
| ▲ | pphysch 8 days ago | parent [-] | | lot_of_html isn't a string literal with dangerous elements smooshed into the trusted scaffolding like an f-string would do. It's a template instance that still needs to be safely processed into a renderable string, e.g. by escaping whatever `evil` evaluates to and even validating the final HTML syntax. | | |
| ▲ | kazinator 8 days ago | parent [-] | | I can easily end up unsafely processed. It's a footgun. And why would you be validating HTML on the fly, when it's coming from your program, not as an input into it. Even if you can do it at program startup once for each template, it's still pointless overhead. The whole thing is wrongheaded; exactly the kind of stove-pipe people end up inventing when they don't have metaprogramming. | | |
| ▲ | zahlman 8 days ago | parent | next [-] | | > I can easily end up unsafely processed. No, that isn't how it works. The unprocessed version is not a `str` instance and doesn't implement `__str__`: > This is because Template instances are intended to be used by template processing code, which may return a string or any other type. There is no canonical way to convert a Template to a string. If you tried to use the Template directly as if it were a string, you'd get either a TypeError or completely malformed HTML (the `repr` of the Template instance, which would look very different). >And why would you be validating HTML on the fly You wouldn't be; you'd be escaping user-generated content that tries to break a page by including HTML markup. | | |
| ▲ | kazinator 7 days ago | parent [-] | | > There is no canonical way to convert a Template to a string. ... but let me assure you it's never the wrong one! | | |
| ▲ | zahlman 7 days ago | parent [-] | | Well, no; the entire point is that there are multiple ways to interpret the Template in context. One possible application is for localization (supposing that the interpolations are objects that can give a localized string on demand, or e.g. integers to be formatted in a locale-aware manner). It should probably be possible to do that with .format anyway, but just as an example. Perhaps someone out there wants to store fragments of SQL within a JSON document, too. The point is to maintain that flexibility, by separating the parsing and formatting steps. |
|
| |
| ▲ | davepeck 8 days ago | parent | prev | next [-] | | > I can easily end up unsafely processed I’m curious how? | |
| ▲ | pphysch 8 days ago | parent | prev [-] | | You don't have to add HTML validation to your processing func, but you brought up invalid syntax up as an issue with string templating. > The whole thing is wrongheaded; exactly the kind of stove-pipe people end up inventing when they don't have metaprogramming. Python has many metaprogramming features. I don't think you understand this feature much less its motivation. How else would you go about adding language support for e.g. HTML and SQL within Python? | | |
| ▲ | kazinator 8 days ago | parent [-] | | On the contrary, I implemented a substantial facsimile of it in a Lisp dialect yesterday; see my comment history. 1> (load "template")
nil
2> (let ((field "name") (table "customers"))
(te `SELECT @field FROM @table`))
#S(template merge #<interpreted fun: lambda (#:self-0073)> strings #("SELECT " " FROM ")
vals #("name" "customers"))
3> *2.(merge)
"SELECT name FROM customers"
4> [*2.vals 0]
"name"
5> (set [*2.vals 0] "id")
"id"
6> *2.(merge)
"SELECT id FROM customers"
7> (upd *2.vals (map upcase-str))
#("ID" "CUSTOMERS")
8> *2.(merge)
"SELECT ID FROM CUSTOMERS"
Unlike template strings, it was done in the language. There already are quasi-strings in the form of `...` syntax. We can quote that syntax (e.g. implicitly as a macro argument) and then pull apart its pieces to construct an object. It should work even in a years-out-of-date installation of the language. No new tooling is required; no changes to syntax highlighting in the editor, nothing.It's a parlor trick that doesn't have any uses. The structured log messages use case is the most promising, because it has a consumer which actually wants the interpolated pieces that it would otherwise have to hackily parse out. I predict that Python will eventually get dedicated HTML syntax: perhaps something that uses indentation to indicate element nesting. Let's "vibe pseudocode" a sketch: html:
div (class='main' id='1'):
p:
"paragraph text"
or whatever. | | |
| ▲ | pphysch 8 days ago | parent [-] | | > Unlike template strings, it was done in the language. This is a disingenuous way to compare a LISP with a language that values syntactic convention and strives to be readable and maintainable by more than one person. > I predict that Python will eventually get dedicated HTML syntax: How do you assign this result to a variable? How is this any better than content: HTML = t"<p>Hello {name}</p>"
| | |
| ▲ | kazinator 8 days ago | parent [-] | | It's a true statement; I made a usable construct that causes template strings to be turned into objects, rather than to perform the string substitution. I did it without changing any syntax, or have to ship a new version of the language. Python has to ship a new version for this; there is no way for existing installations to use the code. I don't have to change anything in my editor setup. So who is it that values syntactic convention? t"abc" is a syntax errror in vast numbers of existing Python installations; how can we call it convention? > How do you assign this result to a variable? That's to be worked out. The "html:" fantasy construct could have a way to do that. When you think of assigning to a variable, the first thing that comes to mind is "a = b" syntax. But, look, the define construct in Python also assigns to a variable: define fun(arg):
...
The imagined html construct could have arguments like to assign an object to a variable, or just spin out textual HTML into a specified stream. I don't want to get into it, but there are obvious ways it could be done such that it hits all sorts of requirements.> How is it any better It renders all of the following problems unrepresentable: mismatched angle brackets, mismatched or unclosed tags, bad attribute syntax, injection. |
|
|
|
|
|
|
|
|