I’m not really clear on why you would use a t-string instead of an f-string if you just want to interpolate format(value, format_spec) ,
Multiple examples in the PEP use the format options, so I’m not sure what’s unclear about the usefulness of conv/fmt_spec. You could be string-formatting only some of the interpolations, or formatting an interpolation that will still be specially processed by the template processor (for example, HTML-escaping), or just doing normal f-string stuff but to a value that’s gonna later be passed to a formatter that expects a Template.
The main reason is that the format spec is an input to the template processor, not value.__format__ .
It’s not immediately clear to me that this is the case. All of the PEP’s examples using the format spec are using it exactly in the “pass to str.format()” way. The PEP itself links to “format specification”, and says “when present they should be respected, and to the extent possible match the behavior of f-strings”. However, since their handling is completely up to the template function right now, this will likely not be true in practice; many/most template functions will be naively written to not process their format args.
My expected behavior would be:
- If a
conv is passed, the value is auto-converted appropriately.
- If a
format_spec is passed:
- If the value has
__format__, that’s auto-called with the format spec.
- If it doesn’t, you get the same TypeError that you do today, when you pass format arguments in an f-string with a value that doesn’t have
__format__.
I can see an argument for diverging from f-string behavior when the value does have __format__ but the interpolation doesn’t have a format_spec. Today, f-strings still call __format__ with no args, because they’ll need a string anyway, but t-strings could reasonably want to leave the value alone by default.
The big idea, I think, is just that today, in every place that uses format_spec, it’s the value’s responsibility to handle that; the context of the value has no input into the process. Inverting that for t-strings, in a completely opaque, case-by-case basis, doesn’t seem like a great idea to me.
Maybe today’s behavior is just because every place doing formatting is expecting to get a str out of it anyway, so the “context” is all identical and there’s no need for a context-specific control in the first place. But if we do want to diverge here, I think some real thought should be given to how that’s done, and how the ecosystem can be expected to actually handle this. The PEP should also showcase such a context-dependent format spec in an example.
Either it is done eagerly, making it impossible to construct templates that don’t use __format__ , or it is done as a property and computed on demand.
I expect it would be done eagerly, as I outlined above. Then, getting .value on the Interpolation would indeed be a normal property access.
As a separate point, I don’t really like that the type of .value would change based on the presence of format_spec .
If you’re doing what the PEP does in several examples, this already essentially happens - the value is used as-is if there’s no conv/fmt, or turned into a string if there is. Under my assumption (possibly incorrect?) that conv/fmt stuff is intended to always act like an f-string, then it’s not even “changing types” - it’s being formatted as requested, and str is the correct type of the resulting value that the template should see.