1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- #!/bin/env python
- import re
- old_pattern = re.compile(r'%\w')
- new_pattern = re.compile(r'\{(\w+(\.\w+|\[\w+\])?)\}')
- __formaters = {}
- def format(text, *a, **kw):
- f = __formaters.get(text)
- if f is None:
- f = formater(text)
- __formaters[text] = f
- return f(*a, **kw)
- #return formater(text)(*a, **kw)
- def formater(text):
- """
- >>> format('%s %s', 3, 2, 7, a=7, id=8)
- '3 2'
- >>> format('%(a)d %(id)s', 3, 2, 7, a=7, id=8)
- '7 8'
- >>> format('{1} {id}', 3, 2, a=7, id=8)
- '2 8'
- >>> class Obj: id = 3
- >>> format('{obj.id} {0.id}', Obj(), obj=Obj())
- '3 3'
- """
- # def arg(k,a,kw):
- # if k.isdigit():
- # return a[int(k)]
- # return kw[k]
- def translator(k):
- if '.' in k:
- name,attr = k.split('.')
- if name.isdigit():
- k = int(name)
- return lambda *a, **kw: getattr(a[k], attr)
- return lambda *a, **kw: getattr(kw[name], attr)
- # elif '[' in k and k.endswith(']'):
- # name,index = k[:k.index('[')],k[k.index('[')+1:-1]
- # def _(*a, **kw):
- # if index.isdigit():
- # return arg(name,a,kw)[int(index)]
- # return arg(name,a,kw)[index]
- # return _
- else:
- if k.isdigit():
- return lambda *a, **kw: a[int(k)]
- return lambda *a, **kw: kw[k]
- args = [translator(k) for k,_1 in new_pattern.findall(text)]
- if args:
- if old_pattern.findall(text):
- raise Exception('mixed format is not allowed')
- f = new_pattern.sub('%s', text)
- def _(*a, **kw):
- return f % tuple([k(*a,**kw) for k in args])
- return _
- elif '%(' in text:
- return lambda *a, **kw: text % kw
- else:
- n = len(old_pattern.findall(text))
- return lambda *a, **kw: text % tuple(a[:n])
- if __name__ == '__main__':
- import doctest
- doctest.testmod()
|