A template stream works pretty much like an ordinary python generator but it can buffer multiple items to reduce the number of total iterations. Per default the output is unbuffered which means that for every unbuffered instruction in the template one unicode string is yielded. If b
| 1189 | |
| 1190 | @implements_iterator |
| 1191 | class TemplateStream(object): |
| 1192 | """A template stream works pretty much like an ordinary python generator |
| 1193 | but it can buffer multiple items to reduce the number of total iterations. |
| 1194 | Per default the output is unbuffered which means that for every unbuffered |
| 1195 | instruction in the template one unicode string is yielded. |
| 1196 | |
| 1197 | If buffering is enabled with a buffer size of 5, five items are combined |
| 1198 | into a new unicode string. This is mainly useful if you are streaming |
| 1199 | big templates to a client via WSGI which flushes after each iteration. |
| 1200 | """ |
| 1201 | |
| 1202 | def __init__(self, gen): |
| 1203 | self._gen = gen |
| 1204 | self.disable_buffering() |
| 1205 | |
| 1206 | def dump(self, fp, encoding=None, errors='strict'): |
| 1207 | """Dump the complete stream into a file or file-like object. |
| 1208 | Per default unicode strings are written, if you want to encode |
| 1209 | before writing specify an `encoding`. |
| 1210 | |
| 1211 | Example usage:: |
| 1212 | |
| 1213 | Template('Hello {{ name }}!').stream(name='foo').dump('hello.html') |
| 1214 | """ |
| 1215 | close = False |
| 1216 | if isinstance(fp, string_types): |
| 1217 | if encoding is None: |
| 1218 | encoding = 'utf-8' |
| 1219 | fp = open(fp, 'wb') |
| 1220 | close = True |
| 1221 | try: |
| 1222 | if encoding is not None: |
| 1223 | iterable = (x.encode(encoding, errors) for x in self) |
| 1224 | else: |
| 1225 | iterable = self |
| 1226 | if hasattr(fp, 'writelines'): |
| 1227 | fp.writelines(iterable) |
| 1228 | else: |
| 1229 | for item in iterable: |
| 1230 | fp.write(item) |
| 1231 | finally: |
| 1232 | if close: |
| 1233 | fp.close() |
| 1234 | |
| 1235 | def disable_buffering(self): |
| 1236 | """Disable the output buffering.""" |
| 1237 | self._next = partial(next, self._gen) |
| 1238 | self.buffered = False |
| 1239 | |
| 1240 | def _buffered_generator(self, size): |
| 1241 | buf = [] |
| 1242 | c_size = 0 |
| 1243 | push = buf.append |
| 1244 | |
| 1245 | while 1: |
| 1246 | try: |
| 1247 | while c_size < size: |
| 1248 | c = next(self._gen) |