94 except IOError, inst: |
94 except IOError, inst: |
95 raise IOError(inst.args[0], _('template file %s: %s') % |
95 raise IOError(inst.args[0], _('template file %s: %s') % |
96 (self.map[t], inst.args[1])) |
96 (self.map[t], inst.args[1])) |
97 return self.template(tmpl, self.filters, **m) |
97 return self.template(tmpl, self.filters, **m) |
98 |
98 |
99 template_re = re.compile(r"[#{]([a-zA-Z_][a-zA-Z0-9_]*)" |
99 template_re = re.compile(r"(?:(?:#(?=[\w\|%]+#))|(?:{(?=[\w\|%]+})))" |
100 r"((%[a-zA-Z_][a-zA-Z0-9_]*)*)" |
100 r"(\w+)((%\w+)*)((\|\w+)*)[#}]") |
101 r"((\|[a-zA-Z_][a-zA-Z0-9_]*)*)[#}]") |
|
102 |
101 |
103 def template(self, tmpl, filters={}, **map): |
102 def template(self, tmpl, filters={}, **map): |
104 lm = map.copy() |
|
105 while tmpl: |
103 while tmpl: |
106 m = self.template_re.search(tmpl) |
104 m = self.template_re.search(tmpl) |
107 if m: |
105 if m: |
108 start, end = m.span(0) |
106 start, end = m.span(0) |
109 s, e = tmpl[start], tmpl[end - 1] |
|
110 key = m.group(1) |
107 key = m.group(1) |
111 if ((s == '#' and e != '#') or (s == '{' and e != '}')): |
108 format = m.group(2) |
112 raise SyntaxError(_("'%s'/'%s' mismatch expanding '%s'") % |
109 fl = m.group(4) |
113 (s, e, key)) |
110 |
114 if start: |
111 if start: |
115 yield tmpl[:start] |
112 yield tmpl[:start] |
|
113 |
116 v = map.get(key, "") |
114 v = map.get(key, "") |
117 v = callable(v) and v(**map) or v |
115 if callable(v): |
118 |
116 v = v(**map) |
119 format = m.group(2) |
|
120 fl = m.group(4) |
|
121 |
117 |
122 if format: |
118 if format: |
123 try: |
119 if not hasattr(v, '__iter__'): |
124 q = v.__iter__ |
|
125 except AttributeError: |
|
126 raise SyntaxError(_("Error expanding '%s%s'") |
120 raise SyntaxError(_("Error expanding '%s%s'") |
127 % (key, format)) |
121 % (key, format)) |
128 for i in q(): |
122 lm = map.copy() |
|
123 for i in v: |
129 lm.update(i) |
124 lm.update(i) |
130 yield self(format[1:], **lm) |
125 yield self(format[1:], **lm) |
131 |
126 |
132 v = "" |
127 v = "" |
133 |
128 |