PEP 750: Tag Strings For Writing Domain-Specific Languages

I realised I’m making some assumptions around the “split constructor signature” idea that neither I nor @zuo have explicitly stated (and my assumptions may not be the same as @zuo’s), so writing those down:

  1. I’m assuming the basic type creation signature would be a simplified formatting syntax that only supports auto-numbered style format strings (no field expressions), and accepts an iterable of values. The expr field on the interpolations would be populated with the empty string to indicate the lack of an explicit expression in the template definition.
  2. If private re-style caching of the dynamic templates is included, it would just use a regular Template instance with the field value attributes set to either Ellipsis or None (I don’t think the choice matters much, since the caching would be a private API)
  3. Supporting full dynamic templating would be deferred to a later PEP (more on that below)
  4. The final line of the default constructor would be defined as return cls.from_segments(*segments), so subclasses only need to override Template.from_segments to change the way construction works (such as pre-quoting replacement field values, so naive formatting becomes safe).

The reason I’d still like to defer full dynamic template field formatting (with class methods like Template.from_format and Template.from_format_map) is that we don’t have a nice building block that would let us easily represent the dynamic attribute and subscript retrieval that the full dynamic string formatting syntax supports. (I’m less worried about format string interpolation, since that can be handled by “templating the template”)

Specifically things like {0.metrics.weight} and {players[0].name} (inspired by the examples in string — Common string operations — Python 3.13.0 documentation).

While I think these could reasonably be represented as a lookup_chain list consisting of itemgetter() and attrgetter() instances, there are enough additional questions raised that it seems worth postponing these topics to a PEP that can fully focus on them, separately from the underlying foundation of the template string syntax definition and implementation.

Since I now also think we’d want to keep UnboundField and UnboundTemplate as their own types (separate from the bound versions, since we can’t actually make them behave identically due to the missing field value information in the unbound variants), accepting PEP 750 without these features wouldn’t be locking us out of anything. Even if PEP 750 doesn’t split the construction signature, we’re not locked out of anything - it just means anyone wanting to do dynamic templating in the meantime would need to build their own on top of string.Formatter instead of Template providing a native way to do it.

Once UnboundTemplate and UnboundField were defined, then the dynamic template caching could be defined in terms of those, and hence provide a foundation for offering Template.from_format and Template.from_format_map.

1 Like