sashank_1509 9 minutes ago

Why does this need to be a language feature. This could just be a separate library, we could use brackets instead of a letter before a string. I fear, Python is going down the path of C++

  • jsnell a minute ago

    It being a language feature gives you controlled access to the lexical scope, such that the template string can refer to variables by name rather than having to pass each value as a parameter. Doing it via parameters is repetitive and/or error-prone.

TekMol 43 minutes ago

Will this allow neat SQL syntax like the following?

    city = 'London'
    min_age = 21
    # Find all users in London who are 21 or older:
    users = db.get(t'
        SELECT * FROM users
        WHERE city={city} AND age>{min_age}
    ')
If the db.get() function accepts a template, it should, right?

This would be the nicest way to use SQL I have seen yet.

  • jbaiter 33 minutes ago

    Thanks, I hate it. While it's nice syntactic sugar, the difference between an SQL injection vulnerability and a properly parametrized query is now a single letter that's easily missed

    • JimDabell 13 minutes ago

      The t-string produces a Template object without a __str__() method. You can’t mistakenly use an f-string in its place. Either the code expects a string, in which case passing it a Template would blow it up, or the code expects a Template, in which case passing it a string would blow it up.

    • baggiponte 31 minutes ago

      Type checkers to the rescue ahaha I think db.get could also raise if the type does not match?

    • TekMol 31 minutes ago

      I guess that is a misunderstanding on your side, about how templates work. Less hate and more love might help to avoid this type of hotheaded misconception ;-)

      Why do you think changing a letter would cause a vulnerability? Which letter do you mean?

      • hyperbovine 26 minutes ago

        OP is referring to swapping t with f.

        • TekMol 24 minutes ago

          That would result in a string passed to get() and raise an error as get() operates on a template, not on a string.

          • baegi a few seconds ago

            except if get() can also accept a raw string, which is likely

      • codesnik 25 minutes ago

        f'' vs t'' probably.

        • tannhaeuser 11 minutes ago

          Wow that's only slightly better than using the lowercase letter L vs the digit 1 or letter O vs zero to convey a significant difference.

runekaagaard an hour ago

It feels a bit like "cheating" that new x-string features are built-in only. It would be cool to be able to do:

    from foo import bar
    bar"zoop"
  • masklinn an hour ago

    A t-string is a literal for a Template object which is a data hoilder, it doesn't actually do anything, so you would simply call

        bar(t"zoop")
  • thund 27 minutes ago

    Use a function?

        bar(“zoop”)
    
    It’s just syntax, like we used to have

        print “foo” 
    
    that later became

        print(“foo”)
  • Timwi 44 minutes ago

    True. Then you could use

      sql"..."
      html"..."
    
    for each of the given examples and achieve some runtime type safety.
sgt 21 minutes ago

Will it be a performance boost if Django's template engine started using t-strings internally?

nezirus 2 hours ago

Maybe this could be useful to libraries like psycopg3 to use something more simple/natural instead of this:

https://www.psycopg.org/psycopg3/docs/api/sql.html

(while I also agree it gets crowded with yet another string prefix)

  • dtech an hour ago

    That's the exact use case. Basically these are syntactic sugar for a very similar function signature.

pizza 2 hours ago

Looks useful for embedding interpreters

enescakir 2 hours ago

Not sure about introducing yet another string prefix. Between f-strings, raw strings, and i18n stuff, it’s already getting crowded. Curious how readable this will be in large codebases.

  • wodenokoto 2 hours ago

    I'm of the opposite opinion. Let's set the prefixes free!

        from sql import sql
    
        query = sql"SELECT user_id, user_name FROM {user_table_versioned} WHERE user_name = {user_name}"
    • dmurray an hour ago

      How would this be different from a function sql() that operates on one of these new t-strings?

      The syntactic sugar of changing it from sql(t"...") doesn't seem particularly valuable. The novel thing about t-strings is that they change the parsing at compile-time.

      • Timwi 38 minutes ago

        > The syntactic sugar of changing it from sql(t"...") doesn't seem particularly valuable.

        It's valuable because:

        - IDEs could then syntax-highlight SQL inside of SQL strings and HTML inside of HTML strings

        - You can't accidentally pass an HTML string to your SQL library

      • stavros an hour ago

        It wouldn't be different, but it would be more convenient because we no longer have to count the number of %s, you'd put the variable inline.

        • masklinn an hour ago

          That's... already the case of t-strings?

          • stavros an hour ago

            Yes, that's my point. The GP was already talking about a t-string.

            • masklinn 43 minutes ago

              dmurray was comparing a hypothetical sql"..." with sql(t"..."). There are no %s either way.

    • mcintyre1994 an hour ago

      This is how JavaScript does it with tagged template literals.

      Your sql there would just be a function that receives the array of strings/values and returns whatever.

  • albert_e an hour ago

    "Yet another" is not my main worry

    The concept of prefixes itself feels a little deviant from readable code that is close to human language -- which is the spirit of Python

    • empiko 20 minutes ago

      Additionally, it will probably be confusing that it is called a t-string but it is actually a constructor for a Template object and not string at all. I would rather see a new special term `template` than this.

    • Timwi 36 minutes ago

      The single letter f or t does make it unnatural to read, but if it were sql"..." or html"...", I think that would help with that.

  • mulmboy an hour ago

    Are there string prefixes for i18n stuff?

    • Biganon an hour ago

      They're probably talking about the convention of using _ as an alias for `translate`

oulipo 2 hours ago

Nice, so it's a kind of "limited DSL" inside python that's easy to extend

avereveard 2 hours ago

what's the tldr difference between this and .format ?

  • jitl 2 hours ago

    It’s injection safe and compostable, and the resulting object retains the original values you interpolate in. This makes it useful for building SQL queries with prepared arguments for example.

  • hk__2 39 minutes ago

    It’s on a meta level: instead of formatting the string, it returns an object that contains both the format string and its argument. Library author can then implement whatever format function they want, for example one that escapes the interpolated strings.

  • earnestinger an hour ago

    It’s custom .format implementation. (You access the placeholder and value and produce the string)

7734128 an hour ago

Sure, this avoids issues with SQL injections. However, I have a hard time imagining any developer who would both make such fundamental errors with f-strings currently and also switching to this option when it ships.

Seems like a self selection which renders this meaningless, to some extent :/

  • masklinn an hour ago

    > However, I have a hard time imagining any developer who would both make such fundamental errors with f-strings currently and also switching to this option when it ships.

    t-strings are a different type (both static and dynamic), f-strings are not. So t-strings can be mandated at the API level, forcing the developer into "proper" usage.

    That is, you need third-party tools to differentiate between

        some_call("safe literal string")
    
    and

        some_call(f"unsafe dynamically created string")
    
    That is not the case when it comes to t-strings, `some_call` can typecheck internally that it got a t-string, and reject regular strings entirely.

    Although some space probably needs to be made for composing t-strings together in case of e.g. runtime variation in items or their count. Facetting for instance. I don't know if that's a native affordance of t-strings.

    • Timwi 42 minutes ago

      But that would require any SQL library you're currently using to make the breaking change of no longer allowing strings.

      • baggiponte 29 minutes ago

        sqlalchemy doesn’t really accepts strings - if you do, you need to pass them into a “conn.execute(text(…))”, so end users should not face a breaking change.

damnitbuilds an hour ago

I enjoy f-strings, I guess some people need these.

And I love Python but, having been through 2->3 ( occasionally still going through it! ) whenever I see a new language feature my first thought is "Thank goodness it doesn't break everything that went before it".

  • stavros an hour ago

    Yeah but it's been 17 years, maybe it's time to put the PTSD behind us. We're almost at a point where the current generation of programmers wasn't even programming when that happened.

    • rglullis 15 minutes ago

      > We're almost at a point where the current generation of programmers wasn't even programming when that happened

      I've been programming with Python since 2006, I think most of the systems were based on 2.4 at the time. I've been one of those who switched to Python 3 somewhat late, waiting for some major libraries to ship python 3 packages - celery and Twisted were one of the biggest holdouts - so I remember that the first project where all my dependencies were ready for python 3 was around 2015.

      This is to say: even seasoned developers who were conservative around the migration have spent more time working with Python 3 than Python 2. There simply is no reason anymore to be talking about python 2.

    • nightfly 7 minutes ago

      Python2 code didn't disappear when Python3 came out. At my work we're _still_ occasionally having to help people migrate code that was written for python2

m2f2 an hour ago

If this is just for sql queries ... it'd be overkill especially where you need to compare the usual PREPARE statements with the hassle of keeping everyone on 3.14 and above.

  • bazoom42 28 minutes ago

    Could also be used to prevent html injection.