Add custom conversion types for line formatting

Is there any way in python to add extra conversion types to string formatting?

The standard conversion types used in % -based formatting are strings such as s for strings, d for decimals, etc. What I would like to do is add a new character for which I can specify a custom handler (for example, a lambda function) that will return a string to be inserted.

For example, I would like to add h as a conversion type to indicate that the string should be escaped for use in HTML. As an example:

 #!/usr/bin/python print "<title>%(TITLE)h</title>" % {"TITLE": "Proof that 12 < 6"} 

And this will use cgi.escape on "TITLE" to create the following output:

 <title>Proof that 12 &lt; 6</title> 
+7
python printf string-formatting
source share
3 answers

You can create a custom formatter for html templates:

 import string, cgi class Template(string.Formatter): def format_field(self, value, spec): if spec.endswith('h'): value = cgi.escape(value) spec = spec[:-1] + 's' return super(Template, self).format_field(value, spec) print Template().format('{0:h} {1:d}', "<hello>", 123) 

Please note that unlike Martijn's answer, all conversions occur inside the template class, no input changes are required.

+12
source share

Not with % formatting, no, this is not possible for expansion.

You can specify various formatting options when using the new line syntax defined for str.format() and format() . Custom types can implement the __format__() method, which will be called using the format specification used in the template string:

 import cgi class HTMLEscapedString(unicode): def __format__(self, spec): value = unicode(self) if spec.endswith('h'): value = cgi.escape(value) spec = spec[:-1] + 's' return format(value, spec) 

This requires that you use your own type for strings:

 >>> title = HTMLEscapedString(u'Proof that 12 < 6') >>> print "<title>{:h}</title>".format(title) <title>Proof that 12 &lt; 6</title> 

In most cases, it is easier to format the string before passing it to the template or use a special HTML template library such as Chameleon, Mako or Jinja2; These HTML descriptors are for you.

+7
source share

I'm a little late to the party, but here's what I do based on the idea at https://mail.python.org/pipermail/python-ideas/2011-March/009426.html

 >>> import string, cgi >>> from xml.sax.saxutils import quoteattr >>> class MyFormatter(string.Formatter): def convert_field(self, value, conversion, _entities={'"': '&quot;'}): if 'Q' == conversion: return quoteattr(value, _entities) else: return super(MyFormatter, self).convert_field(value, conversion) >>> fmt = MyFormatter().format >>> fmt('{0!Q}', '<hello> "world"') '"&lt;hello&gt; &quot;world&quot;"' 
+2
source share

All Articles