Another, and hopefully final round of edits.

This commit is contained in:
Barry Warsaw 2004-09-18 20:53:35 +00:00
parent 3fd244d830
commit 24bd216f0c
1 changed files with 56 additions and 49 deletions

View File

@ -43,11 +43,11 @@ Rationale
A Simpler Proposal
We propose the addition of a new class -- called 'Template', which
will live in the string module -- derived from the built-in
unicode type. The Template class supports new rules for string
substitution; its value contains placeholders, introduced with the
$ character. The following rules for $-placeholders apply:
We propose the addition of a new class, called 'Template', which
will live in the string module. The Template class supports new
rules for string substitution; its value contains placeholders,
introduced with the $ character. The following rules for
$-placeholders apply:
1. $$ is an escape; it is replaced with a single $
@ -63,43 +63,48 @@ A Simpler Proposal
If the $ character appears at the end of the line, or is followed
by any other character than those described above, a ValueError
will be raised at interpolation time. Values in the mapping will
be converted to Unicode strings by calling the built-in unicode()
function, using its default arguments.
will be raised at interpolation time. Values in mapping are
converted automatically to strings.
No other characters have special meaning, however it is possible
to derive from the Template class to define different rules for
the placeholder. For example, a derived class could allow for
periods in the placeholder (e.g. to support a kind of dynamic
namespace and attribute path lookup).
to derive from the Template class to define different substitution
rules. For example, a derived class could allow for periods in
the placeholder (e.g. to support a kind of dynamic namespace and
attribute path lookup), or could define a delimiter character
other than '$'.
Once the Template has been created, substitutions can be performed
using traditional Python syntax. For example:
by calling one of two methods:
- substitute(). This method returns a new string which results
when the values of a mapping are substituted for the
placeholders in the Template. If there are placeholders which
are not present in the mapping, a KeyError will be raised.
- safe_substitute(). This is similar to the substitute() method,
except that KeyErrors are never raised (due to placeholders
missing from the mapping). When a placeholder is missing, the
original placeholder will appear in the resulting string.
Here are some examples:
>>> from string import Template
>>> mapping = dict(name='Guido', country='the Netherlands')
>>> s = Template('${name} was born in ${country}')
>>> print s % mapping
>>> print s.substitute(name='Guido', country='the Netherlands')
Guido was born in the Netherlands
Another class is provided which derives from Template. This class
is called 'SafeTemplate' and supports rules identical to those
above. The difference between Template instances and SafeTemplate
instances is that in SafeTemplate if a placeholder is missing from
the interpolation mapping, no KeyError is raised. Instead, the
original placeholder is included in the result string unchanged.
For example:
>>> from string import Template, SafeTemplate
>>> mapping = dict(name='Guido', country='the Netherlands')
>>> s = Template('$who was born in $country')
>>> print s % mapping
>>> print s.substitute(name='Guido')
Traceback (most recent call last):
[...traceback omitted...]
KeyError: u'who'
>>> s = SafeTemplate('$who was born in $country')
>>> print s % mapping
$who was born in the Netherlands
[...]
KeyError: 'country'
>>> print s.safe_substitute(name='Guido')
Guido was born in ${country}
The signature of substitute() and safe_substitute() allows for
passing the mapping of placeholders to values, either as a single
dictionary-like object in the first positional argument, or as
keyword arguments as shown above. The exact details and
signatures of these two methods is reserved for the standard
library documentation.
Why `$' and Braces?
@ -141,9 +146,9 @@ Comparison to PEP 215
placeholder in the original $-string.
The interesting thing is that the Template class defined in this
PEP has nothing to say about the values that are substituted for
the placeholders. Thus, with a little extra work, it's possible
to support PEP 215's functionality using existing Python syntax.
PEP is designed for inheritance and, with a little extra work,
it's possible to support PEP 215's functionality using existing
Python syntax.
For example, one could define subclasses of Template and dict that
allowed for a more complex placeholder syntax and a mapping that
@ -152,24 +157,26 @@ Comparison to PEP 215
Internationalization
The implementation supports internationalization magic by keeping
the original string value intact. In fact, all the work of the
special substitution rules are implemented by overriding the
__mod__() operator. However the string value of a Template (or
SafeTemplate) is the string that was passed to its constructor.
The implementation supports internationalization by recording the
original template string in the Template instance's 'template'
attribute. This attribute would serve as the lookup key in an
gettext-based catalog. It is up to the application to turn the
resulting string back into a Template for substitution.
This approach allows a gettext-based internationalized program to
use the Template instance as a lookup into the catalog; in fact
gettext doesn't care that the catalog key is a Template. Because
the value of the Template is the original $-string, translators
also never need to use %-strings. The right thing will happen at
run-time.
However, the Template class was designed to work more intuitively
in an internationalized application, by supporting the mixing-in
of Template and unicode subclasses. Thus an internationalized
application could create an application-specific subclass,
multiply inheriting from Template and unicode, and using instances
of that subclass as the gettext catalog key. Further, the
subclass could alias the special __mod__() method to either
.substitute() or .safe_substitute() to provide a more traditional
string/unicode like %-operator substitution syntax.
Reference Implementation
A SourceForge patch[5] is available which implements this
proposal, include unit tests and documentation changes.
The implementation has been committed to the Python 2.4 source tree.
References