# HG changeset patch
# Parent 924949fd71673266ccb00169f99ae7cd47496d16
output: refactor code relative to the token serialization cache (introduced in [1038]).
In preparation for fixing #429.
diff -r 924949fd7167 genshi/output.py
|
a
|
b
|
def get_serializer(method='xml', **kwarg |
| 79 | 79 | return method(**kwargs) |
| 80 | 80 | |
| 81 | 81 | |
| | 82 | def _prepare_cache(use_cache=True): |
| | 83 | """Prepare a private token serialization cache. |
| | 84 | |
| | 85 | :param use_cache: boolean indicating whether a real cache should |
| | 86 | be used or not. If not, the returned functions |
| | 87 | are no-ops. |
| | 88 | |
| | 89 | :return: emit and get functions, for storing and retrieving |
| | 90 | serialized values from the cache. |
| | 91 | """ |
| | 92 | cache = {} |
| | 93 | if use_cache: |
| | 94 | def _emit(kind, input, output): |
| | 95 | cache[kind, input] = output |
| | 96 | return output |
| | 97 | def _get(kind, input): |
| | 98 | return cache.get((kind, input)) |
| | 99 | else: |
| | 100 | def _emit(kind, input, output): |
| | 101 | return output |
| | 102 | def _get(kind, input): |
| | 103 | pass |
| | 104 | return _emit, _get, cache |
| | 105 | |
| | 106 | |
| 82 | 107 | class DocType(object): |
| 83 | 108 | """Defines a number of commonly used DOCTYPE declarations as constants.""" |
| 84 | 109 | |
| … |
… |
class XMLSerializer(object): |
| 204 | 229 | self.filters.append(DocTypeInserter(doctype)) |
| 205 | 230 | self.cache = cache |
| 206 | 231 | |
| | 232 | def _prepare_cache(self): |
| | 233 | return _prepare_cache(self.cache)[:2] |
| | 234 | |
| 207 | 235 | def __call__(self, stream): |
| 208 | 236 | have_decl = have_doctype = False |
| 209 | 237 | in_cdata = False |
| 210 | | |
| 211 | | cache = {} |
| 212 | | cache_get = cache.get |
| 213 | | if self.cache: |
| 214 | | def _emit(kind, input, output): |
| 215 | | cache[kind, input] = output |
| 216 | | return output |
| 217 | | else: |
| 218 | | def _emit(kind, input, output): |
| 219 | | return output |
| | 238 | _emit, _get = self._prepare_cache() |
| 220 | 239 | |
| 221 | 240 | for filter_ in self.filters: |
| 222 | 241 | stream = filter_(stream) |
| 223 | 242 | for kind, data, pos in stream: |
| 224 | | cached = cache_get((kind, data)) |
| | 243 | cached = _get(kind, data) |
| 225 | 244 | if cached is not None: |
| 226 | 245 | yield cached |
| 227 | | |
| 228 | 246 | elif kind is START or kind is EMPTY: |
| 229 | 247 | tag, attrib = data |
| 230 | 248 | buf = ['<', tag] |
| … |
… |
class XHTMLSerializer(XMLSerializer): |
| 323 | 341 | drop_xml_decl = self.drop_xml_decl |
| 324 | 342 | have_decl = have_doctype = False |
| 325 | 343 | in_cdata = False |
| 326 | | |
| 327 | | cache = {} |
| 328 | | cache_get = cache.get |
| 329 | | if self.cache: |
| 330 | | def _emit(kind, input, output): |
| 331 | | cache[kind, input] = output |
| 332 | | return output |
| 333 | | else: |
| 334 | | def _emit(kind, input, output): |
| 335 | | return output |
| | 344 | _emit, _get = self._prepare_cache() |
| 336 | 345 | |
| 337 | 346 | for filter_ in self.filters: |
| 338 | 347 | stream = filter_(stream) |
| 339 | 348 | for kind, data, pos in stream: |
| 340 | | cached = cache_get((kind, data)) |
| | 349 | cached = _get(kind, data) |
| 341 | 350 | if cached is not None: |
| 342 | 351 | yield cached |
| 343 | 352 | |
| … |
… |
class HTMLSerializer(XHTMLSerializer): |
| 454 | 463 | noescape_elems = self._NOESCAPE_ELEMS |
| 455 | 464 | have_doctype = False |
| 456 | 465 | noescape = False |
| 457 | | |
| 458 | | cache = {} |
| 459 | | cache_get = cache.get |
| 460 | | if self.cache: |
| 461 | | def _emit(kind, input, output): |
| 462 | | cache[kind, input] = output |
| 463 | | return output |
| 464 | | else: |
| 465 | | def _emit(kind, input, output): |
| 466 | | return output |
| | 466 | _emit, _get = self._prepare_cache() |
| 467 | 467 | |
| 468 | 468 | for filter_ in self.filters: |
| 469 | 469 | stream = filter_(stream) |
| 470 | 470 | for kind, data, _ in stream: |
| 471 | | output = cache_get((kind, data)) |
| | 471 | output = _get(kind, data) |
| 472 | 472 | if output is not None: |
| 473 | 473 | yield output |
| 474 | 474 | if (kind is START or kind is EMPTY) \ |
| … |
… |
class NamespaceFlattener(object): |
| 626 | 626 | self.cache = cache |
| 627 | 627 | |
| 628 | 628 | def __call__(self, stream): |
| 629 | | cache = {} |
| 630 | | cache_get = cache.get |
| 631 | | if self.cache: |
| 632 | | def _emit(kind, input, output, pos): |
| 633 | | cache[kind, input] = output |
| 634 | | return kind, output, pos |
| 635 | | else: |
| 636 | | def _emit(kind, input, output, pos): |
| 637 | | return output |
| 638 | | |
| 639 | 629 | prefixes = dict([(v, [k]) for k, v in self.prefixes.items()]) |
| 640 | 630 | namespaces = {XML_NAMESPACE.uri: ['xml']} |
| | 631 | _emit, _get, cache = _prepare_cache(self.cache) |
| 641 | 632 | def _push_ns(prefix, uri): |
| 642 | 633 | namespaces.setdefault(uri, []).append(prefix) |
| 643 | 634 | prefixes.setdefault(prefix, []).append(uri) |
| … |
… |
class NamespaceFlattener(object): |
| 668 | 659 | _gen_prefix = _gen_prefix().next |
| 669 | 660 | |
| 670 | 661 | for kind, data, pos in stream: |
| 671 | | output = cache_get((kind, data)) |
| | 662 | output = _get(kind, data) |
| 672 | 663 | if output is not None: |
| 673 | 664 | yield kind, output, pos |
| 674 | 665 | |
| … |
… |
class NamespaceFlattener(object): |
| 701 | 692 | attrname = '%s:%s' % (prefix, attrname) |
| 702 | 693 | new_attrs.append((attrname, value)) |
| 703 | 694 | |
| 704 | | yield _emit(kind, data, (tagname, Attrs(ns_attrs + new_attrs)), pos) |
| | 695 | data = _emit(kind, data, (tagname, Attrs(ns_attrs + new_attrs))) |
| | 696 | yield kind, data, pos |
| 705 | 697 | del ns_attrs[:] |
| 706 | 698 | |
| 707 | 699 | elif kind is END: |
| … |
… |
class NamespaceFlattener(object): |
| 711 | 703 | prefix = namespaces[tagns][-1] |
| 712 | 704 | if prefix: |
| 713 | 705 | tagname = '%s:%s' % (prefix, tagname) |
| 714 | | yield _emit(kind, data, tagname, pos) |
| | 706 | yield kind, _emit(kind, data, tagname), pos |
| 715 | 707 | |
| 716 | 708 | elif kind is START_NS: |
| 717 | 709 | prefix, uri = data |