Welcome, guest | Sign In | My Account | Store | Cart

Replaces %(name)s style formatting with [name] style formatting. Custom open and close delimiters can be specified. Useful for templates exposed to end-users.

Python, 25 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
"""Doctests for templates with bracketed placeholders

>>> s = 'People of [planet], take us to your leader.'
>>> d = dict(planet='Earth')
>>> print convert_template(s) % d
People of Earth, take us to your leader.

>>> s = 'People of <planet>, take us to your leader.'
>>> print convert_template(s, '<', '>') % d
People of Earth, take us to your leader.

"""

import re

def convert_template(template, opener='[', closer=']'):
    opener = re.escape(opener)
    closer = re.escape(closer)
    pattern = re.compile(opener + '([_A-Za-z][_A-Za-z0-9]*)' + closer)
    return re.sub(pattern, r'%(\1)s', template.replace('%','%%'))


if __name__ == '__main__':
    import doctest
    print 'Doctest results: ', doctest.testmod()

Python's % formatting operator is versatile, complex, and not usually appropriate to expose to end users. In Py2.4, the string.Template class offers an alternative using $name, ${name}, and $$. If desired, a custon delimiter may be substituted for $. This allows support for formats like %name.

Since the new class does not support a style with paired opening and closing delimiters, this recipe is offered as an alternative. The opening/closing style may be more familiar to the user or may be a design requirement.

Multi-character delimiters are supported (for example, opener='<<', closer='>>'). Also, it is possible for the opener and closer to be the same character but it is not recommended since a single misplaced delimiter could mess-up multiple placeholders.

The recipe could be extended to include an escape character; however, it is probably not needed because a placeholder is only recognized as a contigous grouping of an opener, python identifier, and closer. A standalone opener or closer will be skipped.

2 comments

Stephen Ferg 17 years, 2 months ago  # | flag

Just for folks who might be searching for recipes, you probably want to correct the spelling of the last word of the name to "substitution".

Paul Morrow 17 years, 2 months ago  # | flag

Small change to support percent signs already in the template. Nice idea. Makes templates much more new-user friendly. But so that you don't have problems with templates that contain percent signs, you might want to change the return statement to be

return re.sub(pattern, r'%(\1)s', template.replace('%','%%'))

Then you can do things like

>>> s = 'People of [planet], take 15% of us to your leader.'
>>> print convert_template(s) % d
People of Earth, take 15% of us to your leader.