Show More
@@ -21,7 +21,7 b' def parsestring(s, quoted=True):' | |||||
21 |
|
21 | |||
22 | return s.decode('string_escape') |
|
22 | return s.decode('string_escape') | |
23 |
|
23 | |||
24 |
class |
|
24 | class engine(object): | |
25 | '''template expansion engine. |
|
25 | '''template expansion engine. | |
26 |
|
26 | |||
27 | template expansion works like this. a map file contains key=value |
|
27 | template expansion works like this. a map file contains key=value | |
@@ -44,6 +44,68 b' class templater(object):' | |||||
44 | template_re = re.compile(r"(?:(?:#(?=[\w\|%]+#))|(?:{(?=[\w\|%]+})))" |
|
44 | template_re = re.compile(r"(?:(?:#(?=[\w\|%]+#))|(?:{(?=[\w\|%]+})))" | |
45 | r"(\w+)(?:(?:%(\w+))|((?:\|\w+)*))[#}]") |
|
45 | r"(\w+)(?:(?:%(\w+))|((?:\|\w+)*))[#}]") | |
46 |
|
46 | |||
|
47 | def __init__(self, loader, filters={}, defaults={}): | |||
|
48 | self.loader = loader | |||
|
49 | self.filters = filters | |||
|
50 | self.defaults = defaults | |||
|
51 | ||||
|
52 | def process(self, t, map): | |||
|
53 | '''Perform expansion. t is name of map element to expand. map contains | |||
|
54 | added elements for use during expansion. Is a generator.''' | |||
|
55 | tmpl = self.loader(t) | |||
|
56 | iters = [self._process(tmpl, map)] | |||
|
57 | while iters: | |||
|
58 | try: | |||
|
59 | item = iters[0].next() | |||
|
60 | except StopIteration: | |||
|
61 | iters.pop(0) | |||
|
62 | continue | |||
|
63 | if isinstance(item, str): | |||
|
64 | yield item | |||
|
65 | elif item is None: | |||
|
66 | yield '' | |||
|
67 | elif hasattr(item, '__iter__'): | |||
|
68 | iters.insert(0, iter(item)) | |||
|
69 | else: | |||
|
70 | yield str(item) | |||
|
71 | ||||
|
72 | def _process(self, tmpl, map): | |||
|
73 | '''Render a template. Returns a generator.''' | |||
|
74 | while tmpl: | |||
|
75 | m = self.template_re.search(tmpl) | |||
|
76 | if not m: | |||
|
77 | yield tmpl | |||
|
78 | break | |||
|
79 | ||||
|
80 | start, end = m.span(0) | |||
|
81 | key, format, fl = m.groups() | |||
|
82 | ||||
|
83 | if start: | |||
|
84 | yield tmpl[:start] | |||
|
85 | tmpl = tmpl[end:] | |||
|
86 | ||||
|
87 | if key in map: | |||
|
88 | v = map[key] | |||
|
89 | else: | |||
|
90 | v = self.defaults.get(key, "") | |||
|
91 | if callable(v): | |||
|
92 | v = v(**map) | |||
|
93 | if format: | |||
|
94 | if not hasattr(v, '__iter__'): | |||
|
95 | raise SyntaxError(_("Error expanding '%s%%%s'") | |||
|
96 | % (key, format)) | |||
|
97 | lm = map.copy() | |||
|
98 | for i in v: | |||
|
99 | lm.update(i) | |||
|
100 | yield self.process(format, lm) | |||
|
101 | else: | |||
|
102 | if fl: | |||
|
103 | for f in fl.split("|")[1:]: | |||
|
104 | v = self.filters[f](v) | |||
|
105 | yield v | |||
|
106 | ||||
|
107 | class templater(object): | |||
|
108 | ||||
47 | def __init__(self, mapfile, filters={}, defaults={}, cache={}, |
|
109 | def __init__(self, mapfile, filters={}, defaults={}, cache={}, | |
48 | minchunk=1024, maxchunk=65536): |
|
110 | minchunk=1024, maxchunk=65536): | |
49 | '''set up template engine. |
|
111 | '''set up template engine. | |
@@ -79,7 +141,7 b' class templater(object):' | |||||
79 | def __contains__(self, key): |
|
141 | def __contains__(self, key): | |
80 | return key in self.cache or key in self.map |
|
142 | return key in self.cache or key in self.map | |
81 |
|
143 | |||
82 |
def |
|
144 | def load(self, t): | |
83 | '''Get the template for the given template name. Use a local cache.''' |
|
145 | '''Get the template for the given template name. Use a local cache.''' | |
84 | if not t in self.cache: |
|
146 | if not t in self.cache: | |
85 | try: |
|
147 | try: | |
@@ -89,69 +151,14 b' class templater(object):' | |||||
89 | (self.map[t], inst.args[1])) |
|
151 | (self.map[t], inst.args[1])) | |
90 | return self.cache[t] |
|
152 | return self.cache[t] | |
91 |
|
153 | |||
92 | def _process(self, tmpl, map): |
|
|||
93 | '''Render a template. Returns a generator.''' |
|
|||
94 | while tmpl: |
|
|||
95 | m = self.template_re.search(tmpl) |
|
|||
96 | if not m: |
|
|||
97 | yield tmpl |
|
|||
98 | break |
|
|||
99 |
|
||||
100 | start, end = m.span(0) |
|
|||
101 | key, format, fl = m.groups() |
|
|||
102 |
|
||||
103 | if start: |
|
|||
104 | yield tmpl[:start] |
|
|||
105 | tmpl = tmpl[end:] |
|
|||
106 |
|
||||
107 | if key in map: |
|
|||
108 | v = map[key] |
|
|||
109 | else: |
|
|||
110 | v = self.defaults.get(key, "") |
|
|||
111 | if callable(v): |
|
|||
112 | v = v(**map) |
|
|||
113 | if format: |
|
|||
114 | if not hasattr(v, '__iter__'): |
|
|||
115 | raise SyntaxError(_("Error expanding '%s%%%s'") |
|
|||
116 | % (key, format)) |
|
|||
117 | lm = map.copy() |
|
|||
118 | for i in v: |
|
|||
119 | lm.update(i) |
|
|||
120 | t = self._template(format) |
|
|||
121 | yield self._process(t, lm) |
|
|||
122 | else: |
|
|||
123 | if fl: |
|
|||
124 | for f in fl.split("|")[1:]: |
|
|||
125 | v = self.filters[f](v) |
|
|||
126 | yield v |
|
|||
127 |
|
||||
128 | def __call__(self, t, **map): |
|
154 | def __call__(self, t, **map): | |
129 | stream = self.expand(t, **map) |
|
155 | proc = engine(self.load, self.filters, self.defaults) | |
|
156 | stream = proc.process(t, map) | |||
130 | if self.minchunk: |
|
157 | if self.minchunk: | |
131 | stream = util.increasingchunks(stream, min=self.minchunk, |
|
158 | stream = util.increasingchunks(stream, min=self.minchunk, | |
132 | max=self.maxchunk) |
|
159 | max=self.maxchunk) | |
133 | return stream |
|
160 | return stream | |
134 |
|
161 | |||
135 | def expand(self, t, **map): |
|
|||
136 | '''Perform expansion. t is name of map element to expand. map contains |
|
|||
137 | added elements for use during expansion. Is a generator.''' |
|
|||
138 | tmpl = self._template(t) |
|
|||
139 | iters = [self._process(tmpl, map)] |
|
|||
140 | while iters: |
|
|||
141 | try: |
|
|||
142 | item = iters[0].next() |
|
|||
143 | except StopIteration: |
|
|||
144 | iters.pop(0) |
|
|||
145 | continue |
|
|||
146 | if isinstance(item, str): |
|
|||
147 | yield item |
|
|||
148 | elif item is None: |
|
|||
149 | yield '' |
|
|||
150 | elif hasattr(item, '__iter__'): |
|
|||
151 | iters.insert(0, iter(item)) |
|
|||
152 | else: |
|
|||
153 | yield str(item) |
|
|||
154 |
|
||||
155 | def templatepath(name=None): |
|
162 | def templatepath(name=None): | |
156 | '''return location of template file or directory (if no name). |
|
163 | '''return location of template file or directory (if no name). | |
157 | returns None if not found.''' |
|
164 | returns None if not found.''' |
General Comments 0
You need to be logged in to leave comments.
Login now