|
| 1 | +PEP: 802 |
| 2 | +Title: Add `str.template()` Method to Dynamically Construct Template Objects |
| 3 | +Author: Huang Hao Hua <13140752715@163.com> |
| 4 | +Status: Draft |
| 5 | +Type: Standards Track |
| 6 | +Topic: String Formatting |
| 7 | +Created: 2025-08-07 |
| 8 | +Python-Version: 3.13 |
| 9 | +Requires: 750 |
| 10 | +Post-History: 2025-08-07 |
| 11 | + |
| 12 | +Abstract |
| 13 | +======== |
| 14 | + |
| 15 | +This PEP proposes adding a new method ``str.template(*args, **kwargs) -> Template`` |
| 16 | +to the built-in ``str`` type. This method allows dynamically creating template |
| 17 | +objects using the template string syntax introduced in PEP 750. |
| 18 | + |
| 19 | +This complements PEP 750’s ``t""`` syntax by providing a runtime equivalent API |
| 20 | +for dynamic string templating and deferred rendering. |
| 21 | + |
| 22 | +Motivation |
| 23 | +========== |
| 24 | + |
| 25 | +PEP 750 introduces a structured template string syntax ``t""`` as an alternative |
| 26 | +to ``f""`` and ``str.format()``. While ``t""`` allows compile-time template creation, |
| 27 | +there is no standardized way to construct a ``Template`` object dynamically at runtime. |
| 28 | + |
| 29 | +Adding a ``str.template()`` method serves several needs: |
| 30 | + |
| 31 | +- Internationalization systems often generate format strings dynamically. |
| 32 | +- Dynamic UIs or templates may assemble format strings based on user input or context. |
| 33 | +- Reusable templates can be precompiled and stored as structured objects. |
| 34 | +- The API would provide symmetry with ``str.format()``, making it easier to adopt. |
| 35 | + |
| 36 | +Specification |
| 37 | +============= |
| 38 | + |
| 39 | +Method Signature |
| 40 | +---------------- |
| 41 | + |
| 42 | +.. code:: python |
| 43 | +
|
| 44 | + str.template(*args, **kwargs) -> Template |
| 45 | +
|
| 46 | +Behavior |
| 47 | +-------- |
| 48 | + |
| 49 | +- The method returns an instance of the ``Template`` class as defined by PEP 750. |
| 50 | +- The string instance is treated as the template pattern. |
| 51 | +- The passed arguments are used to bind values to the template at creation. |
| 52 | +- Like ``str.format()``, both positional (``{0}``) and keyword (``{name}``) placeholders are supported. |
| 53 | +- The returned ``Template`` object supports deferred rendering via ``__str__`` or explicit ``render()``. |
| 54 | + |
| 55 | +Example Usage |
| 56 | +------------- |
| 57 | + |
| 58 | +.. code:: python |
| 59 | +
|
| 60 | + tpl = "Hello, {name}!".template(name="Alice") |
| 61 | + assert isinstance(tpl, Template) |
| 62 | + print(str(tpl)) # Outputs: Hello, Alice! |
| 63 | +
|
| 64 | + # Dynamic construction |
| 65 | + fmt = "User {id} has status {status}." |
| 66 | + tpl = fmt.template(id=42, status="active") |
| 67 | +
|
| 68 | +Rationale |
| 69 | +========= |
| 70 | + |
| 71 | +- Provides a runtime-compatible API for PEP 750’s static ``t""`` templates. |
| 72 | +- Enables structured templates with delayed interpolation. |
| 73 | +- Offers a migration path from ``.format()`` to structured templating. |
| 74 | +- Useful for applications requiring dynamic template generation and reuse. |
| 75 | +- Mirrors the mental model of ``str.format()``, reducing learning curve. |
| 76 | + |
| 77 | +Backwards Compatibility |
| 78 | +======================= |
| 79 | + |
| 80 | +This is a fully additive proposal. ``str`` currently does not have a ``template()`` |
| 81 | +method, so no code will be broken. |
| 82 | + |
| 83 | +This method has no effect on the legacy ``string.Template`` class or its behavior. |
| 84 | + |
| 85 | +Reference Implementation |
| 86 | +======================== |
| 87 | + |
| 88 | +A sample implementation in pure Python could look like: |
| 89 | + |
| 90 | +.. code:: python |
| 91 | +
|
| 92 | + class Template: |
| 93 | + def __init__(self, pattern, *args, **kwargs): |
| 94 | + self.pattern = pattern |
| 95 | + self.args = args |
| 96 | + self.kwargs = kwargs |
| 97 | +
|
| 98 | + def __str__(self): |
| 99 | + return self.pattern.format(*self.args, **self.kwargs) |
| 100 | +
|
| 101 | + def str_template(self, *args, **kwargs): |
| 102 | + return Template(self, *args, **kwargs) |
| 103 | +
|
| 104 | + str.template = str_template |
| 105 | +
|
| 106 | +In the CPython implementation, this would likely be implemented in C and integrated |
| 107 | +into the ``str`` type’s method table. |
| 108 | + |
| 109 | +Alternatives |
| 110 | +============ |
| 111 | + |
| 112 | +1. **Do nothing**: Continue using string concatenation or ``str.format()``. |
| 113 | +2. **Use a standalone constructor**: Like ``Template.from_string(...)``. This is more verbose and less elegant. |
| 114 | +3. **Inject into ``Template`` class only**: May reduce discoverability compared to a ``str`` method. |
| 115 | + |
| 116 | +Rejected Ideas |
| 117 | +============== |
| 118 | + |
| 119 | +- Overloading ``str.format()`` to support structured templates. |
| 120 | +- Adding new operators (e.g., ``@`` or ``%``) for template binding. |
| 121 | +- Overloading ``t""`` to allow dynamic behavior (breaks simplicity and predictability). |
| 122 | + |
| 123 | +Open Issues |
| 124 | +=========== |
| 125 | + |
| 126 | +- Whether the bound arguments are stored inside the ``Template`` object or applied at render time. |
| 127 | +- Whether ``Template`` should expose a ``.render(...)`` method or rely solely on ``__str__``. |
| 128 | + |
| 129 | +References |
| 130 | +========== |
| 131 | + |
| 132 | +- PEP 750: Structured Template Strings (`https://peps.python.org/pep-0750/`_) |
| 133 | +- PEP 498: Formatted String Literals |
| 134 | +- PEP 3101: Advanced String Formatting |
| 135 | + |
| 136 | +Copyright |
| 137 | +========= |
| 138 | + |
| 139 | +This document has been placed in the public domain. |
| 140 | + |
0 commit comments