[CentralOH] Python % Formatting

Mark Erbaugh mark at microenh.com
Fri Dec 7 18:12:12 CET 2007

Here is my first cut at some code to do what I want.  I've added a
couple of features that weren't in the original request, but should add
some value. See the docstrings below for more information.

Feedback is welcome!



import UserDict

def split_fmt(fmt):
    split a partial format string into the format portion
    and any trailing characters.

    the format string includes all characters up to and
    including the first letter after the ')'

    split_fmt('first)2s.') -> ('first)2s', '.')

    if no formatting field is found return the input and ''
    p = fmt.find(')')
    if p > -1:
        l = len(fmt)
        p += 1
        while p < l:
            if fmt[p].isalpha():
                p += 1
                return fmt[:p], fmt[p:]
                p +=1
    return fmt, ''

class csDict(UserDict.UserDict):
    user dict that returns '' if element not found

    def __getitem__(self, key):
        return self.data.get(key, '')

def cs(fmt, data={}, **kwds):
    implement 'conditional' separator formatting.

    This expands the % mapping formatting.
    i.e. data = {'first': 'Mark', 'midle': 'E.', 'last': 'Erbaugh'}
    fmt = '%(first)s %(middle)s %(last)s'
    fmt % data -> 'Mark E. Erbaugh'

    This is the similar to 'normal' % dict formatting.

    Extensions to % mapping formatting
    if the field referenced does not exist or the data field is
        empty, that field and any characters follwing it are
        skipped. This does not apply to the last field.  Any trailing
        characters or whitespace will be printed. If fields at the end
        are empty, the trailing characters or whitespace from the last
        non-empty field will be skipped

      FMT = '%(first)s %(middle)s %(last)s.'
      data(first, middle, last)
        'Mark', '', 'Erbaugh'  -> 'Mark Erbaugh.'
		(space after middle omitted)
        'Mark', '', '',        -> 'Mark.'
		(spaces after first and middle omitted, period
                after empty last kept)

      FMT = '%(last)s, %(first) %(middle).'
      data (first, middle, last)
        'Mark', '', 'Erbaugh'   -> 'Erbaugh, 'Mark.'
        '', '', 'Erbaugh        -> 'Erbaugh.'  comma after last ommited
            (no further non-blank fields)
        '', 'Edwin', 'Erbaugh   -> 'Erbaugh, Edwin.'
		(space after first omitted)

    data can be a mapping(dict) or keyword parameters or both
    if a keyword parameter is the same as a dict key,
	the keyword parameter  will overwrite the dict value

    def fmt_str(f): return ('%(' + f) % d

    d = {}
    d = csDict(d)
    r = []
    r1 = fmt.split('%(')
    r.append(r1[0]) # first element will not have field to be formatted
    added_last = False
    for i in r1[1:-1]:
        f,t = split_fmt(i)
        if f > '':
            o = fmt_str(f)
            if o > '':
                added_last = True
    f,t = split_fmt(r1[-1]) 
    o = fmt_str(f)
    if o == '' and added_last:
        del r[-1]
    return ''.join(r)

More information about the CentralOH mailing list