41 format uses key to expand each item in list. syntax is |
41 format uses key to expand each item in list. syntax is |
42 {key%format}. |
42 {key%format}. |
43 |
43 |
44 filter uses function to transform value. syntax is |
44 filter uses function to transform value. syntax is |
45 {key|filter1|filter2|...}.''' |
45 {key|filter1|filter2|...}.''' |
|
46 |
|
47 template_re = re.compile(r"(?:(?:#(?=[\w\|%]+#))|(?:{(?=[\w\|%]+})))" |
|
48 r"(\w+)(?:(?:%(\w+))|((?:\|\w+)*))[#}]") |
46 |
49 |
47 def __init__(self, mapfile, filters={}, defaults={}, cache={}): |
50 def __init__(self, mapfile, filters={}, defaults={}, cache={}): |
48 '''set up template engine. |
51 '''set up template engine. |
49 mapfile is name of file to read map definitions from. |
52 mapfile is name of file to read map definitions from. |
50 filters is dict of functions. each transforms a value into another. |
53 filters is dict of functions. each transforms a value into another. |
82 |
85 |
83 def __call__(self, t, **map): |
86 def __call__(self, t, **map): |
84 '''perform expansion. |
87 '''perform expansion. |
85 t is name of map element to expand. |
88 t is name of map element to expand. |
86 map is added elements to use during expansion.''' |
89 map is added elements to use during expansion.''' |
87 m = self.defaults.copy() |
|
88 m.update(map) |
|
89 if not self.cache.has_key(t): |
90 if not self.cache.has_key(t): |
90 try: |
91 try: |
91 self.cache[t] = file(self.map[t]).read() |
92 self.cache[t] = file(self.map[t]).read() |
92 except IOError, inst: |
93 except IOError, inst: |
93 raise IOError(inst.args[0], _('template file %s: %s') % |
94 raise IOError(inst.args[0], _('template file %s: %s') % |
94 (self.map[t], inst.args[1])) |
95 (self.map[t], inst.args[1])) |
95 return self.template(self.cache[t], **m) |
96 tmpl = self.cache[t] |
96 |
97 |
97 template_re = re.compile(r"(?:(?:#(?=[\w\|%]+#))|(?:{(?=[\w\|%]+})))" |
|
98 r"(\w+)((%\w+)*)((\|\w+)*)[#}]") |
|
99 |
|
100 def template(self, tmpl, **map): |
|
101 while tmpl: |
98 while tmpl: |
102 m = self.template_re.search(tmpl) |
99 m = self.template_re.search(tmpl) |
103 if m: |
100 if not m: |
104 start, end = m.span(0) |
101 yield tmpl |
105 key = m.group(1) |
102 break |
106 format = m.group(2) |
103 |
107 fl = m.group(4) |
104 start, end = m.span(0) |
108 |
105 key, format, fl = m.groups() |
109 if start: |
106 |
110 yield tmpl[:start] |
107 if start: |
111 |
108 yield tmpl[:start] |
112 v = map.get(key, "") |
109 tmpl = tmpl[end:] |
113 if callable(v): |
110 |
114 v = v(**map) |
111 if key in map: |
115 |
112 v = map[key] |
116 if format: |
113 else: |
117 if not hasattr(v, '__iter__'): |
114 v = self.defaults.get(key, "") |
118 raise SyntaxError(_("Error expanding '%s%s'") |
115 if callable(v): |
119 % (key, format)) |
116 v = v(**map) |
120 lm = map.copy() |
117 if format: |
121 for i in v: |
118 if not hasattr(v, '__iter__'): |
122 lm.update(i) |
119 raise SyntaxError(_("Error expanding '%s%s'") |
123 yield self(format[1:], **lm) |
120 % (key, format)) |
124 |
121 lm = map.copy() |
125 v = "" |
122 for i in v: |
126 |
123 lm.update(i) |
127 elif fl: |
124 yield self(format, **lm) |
|
125 else: |
|
126 if fl: |
128 for f in fl.split("|")[1:]: |
127 for f in fl.split("|")[1:]: |
129 v = self.filters[f](v) |
128 v = self.filters[f](v) |
130 |
|
131 yield v |
129 yield v |
132 tmpl = tmpl[end:] |
|
133 else: |
|
134 yield tmpl |
|
135 break |
|
136 |
130 |
137 agescales = [("second", 1), |
131 agescales = [("second", 1), |
138 ("minute", 60), |
132 ("minute", 60), |
139 ("hour", 3600), |
133 ("hour", 3600), |
140 ("day", 3600 * 24), |
134 ("day", 3600 * 24), |