Enumerating formatting strings
Michael Spencer
mahs at telcopartners.com
Wed Apr 20 16:00:57 EDT 2005
Bengt Richter wrote:
> On Wed, 20 Apr 2005 11:01:28 +0200, Peter Otten <__peter__ at web.de> wrote:
>
...
>>>>>"%s %(x)s %(y)s" % D()
My experiments suggest that you can have a maximum of one unnamed argument in a
mapping template - this unnamed value evaluates to the map itself
>> ...
>> So under what circumstances is
>>'%s this %(x)s not %% but %s' a valid format string?
Based on the above experiments, never.
I have wrapped up my current understanding in the following class:
>>> s = StringFormatInfo('%s %*.*d %*s')
>>> s
POSITIONAL Template: %s %*.*d %*s
Arguments: ('s', 'width', 'precision', 'd', 'width', 's')
>>> s = StringFormatInfo('%(arg1)s %% %(arg2).*f %()s %s')
>>> s
MAPPING Template: %(arg1)s %% %(arg2).*f %()s %s
Arguments: {'': 's', 'arg1': 's', 'arg2': 'f', None: 's'}
>>>
class StringFormatInfo(object):
parse_format = re.compile(r'''
\% # placeholder
(?:\((?P<name>[\w]*)\))? # 0 or 1 named groups
(?P<conversion>[\#0\-\+]?) # 0 or 1 conversion flags
(?P<width>[\d]* | \*) # optional minimum conversion width
(?:.(?P<precision>[\d]+ | \*))? # optional precision
(?P<lengthmodifier>[hlL]?) # optional length modifier
(?P<type>[diouxXeEfFgGcrs]{1}) # conversion type - note %% omitted
''',
re.VERBOSE
)
"""Wraps a template string and provides information about the number and
kinds of arguments that must be supplied. Call with % to apply the
template to data"""
def __init__(self, template):
self.template = template
self.formats = formats = [m.groupdict() for m in
self.parse_format.finditer(template)]
for format in formats:
if format['name']:
self.format_type = "MAPPING"
self.format_names = dict((format['name'], format['type'])
for format in formats)
break
else:
self.format_type = "POSITIONAL"
format_names = []
for format in formats:
if format['width'] == '*':
format_names.append('width')
if format['precision'] == '*':
format_names.append('precision')
format_names.append(format['type'])
self.format_names = tuple(format_names)
def __mod__(self, values):
return self.template % values
def __repr__(self):
return "%s Template: %s\nArguments: %s" % \
(self.format_type, self.template, self.format_names)
Michael
More information about the Python-list
mailing list