Bengt Richter wrote:
On Wed, 20 Apr 2005 11:01:28 +0200, Peter Otten <[EMAIL PROTECTED]> 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

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to