# HG changeset patch # User cmlenz # Date 1152730059 0 # Node ID 1da51d718391e8b97b7feecf36142f5d0307be5c # Parent ee092ccb3af157524f3e1384fa96a53ecb9cae02 Some more performance tweaks. diff --git a/examples/basic/kidrun.py b/examples/basic/kidrun.py --- a/examples/basic/kidrun.py +++ b/examples/basic/kidrun.py @@ -1,6 +1,9 @@ -from datetime import datetime, timedelta +#!/usr/bin/python +# -*- coding: utf-8 -*- + import os import sys +import time import kid @@ -12,29 +15,25 @@ items=['Number %d' % num for num in range(1, 15)], prefix='#') - start = datetime.now() + start = time.clock() template = kid.Template(file='test.kid', **ctxt) - print ' --> parse stage: ', datetime.now() - start + print ' --> parse stage: %.4f ms' % ((time.clock() - start) * 1000) + + for output in template.generate(): + sys.stdout.write(output) + print times = [] - for i in range(100): - start = datetime.now() - for output in template.generate(): - if i == 0: - sys.stdout.write(output) - if i == 0: - print - else: - sys.stdout.write('.') - sys.stdout.flush() - times.append(datetime.now() - start) + for i in range(1000): + start = time.clock() + list(template.generate()) + times.append(time.clock() - start) + sys.stdout.write('.') + sys.stdout.flush() print - total_ms = sum([t.seconds * 1000 + t.microseconds for t in times]) - print ' --> render stage: %s (avg), %s (min), %s (max):' % ( - timedelta(microseconds=total_ms / len(times)), - timedelta(microseconds=min([t.seconds * 1000 + t.microseconds for t in times])), - timedelta(microseconds=max([t.seconds * 1000 + t.microseconds for t in times]))) + print ' --> render stage: %s ms (average)' % ( + (sum(times) / len(times) * 1000)) if __name__ == '__main__': if '-p' in sys.argv: diff --git a/examples/basic/run.py b/examples/basic/run.py --- a/examples/basic/run.py +++ b/examples/basic/run.py @@ -1,9 +1,9 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from datetime import datetime, timedelta import os import sys +import time from markup.template import Context, TemplateLoader @@ -11,9 +11,9 @@ base_path = os.path.dirname(os.path.abspath(__file__)) loader = TemplateLoader([base_path], auto_reload=True) - start = datetime.now() + start = time.clock() tmpl = loader.load('test.html') - print ' --> parse stage: ', datetime.now() - start + print ' --> parse stage: %.4f ms' % ((time.clock() - start) * 1000) data = dict(hello='', skin='default', hey='ZYX', bozz=None, items=['Number %d' % num for num in range(1, 15)], @@ -22,19 +22,16 @@ print tmpl.generate(Context(**data)).render(method='html') times = [] - for i in range(100): - start = datetime.now() + for i in range(1000): + start = time.clock() list(tmpl.generate(Context(**data))) + times.append(time.clock() - start) sys.stdout.write('.') sys.stdout.flush() - times.append(datetime.now() - start) print - total_ms = sum([t.seconds * 1000 + t.microseconds for t in times]) - print ' --> render stage: %s (avg), %s (min), %s (max)' % ( - timedelta(microseconds=total_ms / len(times)), - timedelta(microseconds=min([t.seconds * 1000 + t.microseconds for t in times])), - timedelta(microseconds=max([t.seconds * 1000 + t.microseconds for t in times]))) + print ' --> render stage: %s ms (average)' % ( + (sum(times) / len(times) * 1000)) if __name__ == '__main__': if '-p' in sys.argv: diff --git a/examples/bench/run.py b/examples/bench/run.py --- a/examples/bench/run.py +++ b/examples/bench/run.py @@ -84,7 +84,7 @@ t = timeit.Timer(setup='from __main__ import %s; render = %s("%s")' % (engine, engine, dirname), stmt='render()') - print '%.2f ms' % (1000 * t.timeit(number=1000) / 1000) + print '%.2f ms' % (1000 * t.timeit(number=2000) / 2000) if __name__ == '__main__': engines = [arg for arg in sys.argv[1:] if arg[0] != '-'] diff --git a/markup/core.py b/markup/core.py --- a/markup/core.py +++ b/markup/core.py @@ -297,14 +297,13 @@ as is. Escaping quotes is generally only required for strings that are to be used in attribute values. """ - if isinstance(text, cls): + if not text: + return cls() + if type(text) is cls: return text - text = unicode(text) - if not text or isinstance(text, cls): - return cls() - text = text.replace('&', '&') \ - .replace('<', '<') \ - .replace('>', '>') + text = unicode(text).replace('&', '&') \ + .replace('<', '<') \ + .replace('>', '>') if quotes: text = text.replace('"', '"') return cls(text) @@ -397,7 +396,6 @@ def __getitem__(self, name): return QName(self.uri + u'}' + name) - __getattr__ = __getitem__ def __repr__(self): diff --git a/markup/output.py b/markup/output.py --- a/markup/output.py +++ b/markup/output.py @@ -20,7 +20,7 @@ except NameError: from sets import ImmutableSet as frozenset -from markup.core import Markup, Namespace, QName +from markup.core import escape, Markup, Namespace, QName from markup.core import DOCTYPE, START, END, START_NS, END_NS, TEXT __all__ = ['Serializer', 'XMLSerializer', 'HTMLSerializer'] @@ -90,7 +90,7 @@ prefix = ns_mapping.get(attr.namespace) if prefix: attrname = '%s:%s' % (prefix, attrname) - buf.append(' %s="%s"' % (attrname, Markup.escape(value))) + buf.append(' %s="%s"' % (attrname, escape(value))) kind, data, pos = stream.next() if kind is END: @@ -111,7 +111,7 @@ yield Markup('' % tagname) elif kind is TEXT: - yield Markup.escape(data, quotes=False) + yield escape(data, quotes=False) class HTMLSerializer(Serializer): @@ -158,8 +158,7 @@ if value: buf.append(' %s' % attr.localname) else: - buf.append(' %s="%s"' % (attr.localname, - Markup.escape(value))) + buf.append(' %s="%s"' % (attr.localname, escape(value))) if tag.localname in self._EMPTY_ELEMS: kind, data, pos = stream.next() @@ -175,7 +174,7 @@ yield Markup('' % tag.localname) elif kind is TEXT: - yield Markup.escape(data, quotes=False) + yield escape(data, quotes=False) class _PushbackIterator(object): diff --git a/markup/path.py b/markup/path.py --- a/markup/path.py +++ b/markup/path.py @@ -123,10 +123,13 @@ yield kind, data, pos depth = 1 while depth > 0: - ev = stream.next() - depth += {START: 1, END: -1}.get(ev[0], 0) - yield ev - test(*ev) + subkind, subdata, subpos = stream.next() + if subkind is START: + depth += 1 + elif subkind is END: + depth -= 1 + yield subkind, subdata, subpos + test(subkind, subdata, subpos) elif result: yield result return Stream(_generate()) diff --git a/markup/template.py b/markup/template.py --- a/markup/template.py +++ b/markup/template.py @@ -896,10 +896,13 @@ content = [(kind, data, pos)] depth = 1 while depth > 0: - ev = stream.next() - depth += {START: 1, END: -1}.get(ev[0], 0) - content.append(ev) - test(*ev) + kind, data, pos = stream.next() + if kind is START: + depth += 1 + elif kind is END: + depth -= 1 + content.append((kind, data, pos)) + test(kind, data, pos) content = list(self._flatten(content, ctxt)) ctxt.push(select=lambda path: Stream(content).select(path))