changeset 70:dd73921530e8 trunk

Use `collections.deque` for the template context stack on Python 2.4, which improves performance if there are many context frame pop/push operations.
author cmlenz
date Tue, 11 Jul 2006 17:40:41 +0000
parents c40a5dcd2b55
children db7c76d337aa
files markup/path.py markup/template.py
diffstat 2 files changed, 24 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/markup/path.py
+++ b/markup/path.py
@@ -15,7 +15,7 @@
 
 import re
 
-from markup.core import QName, Stream
+from markup.core import QName, Stream, START, END, TEXT
 
 __all__ = ['Path']
 
@@ -114,8 +114,6 @@
         @param stream: the stream to select from
         @return: the substream matching the path, or an empty stream
         """
-        from markup.core import END, START
-
         stream = iter(stream)
         def _generate():
             test = self.test()
@@ -212,7 +210,7 @@
         """Node test that matches the context node."""
         axis = 'self'
         def __call__(self, kind, *_):
-            if kind is Stream.START:
+            if kind is START:
                 return True
             return None
 
@@ -220,7 +218,7 @@
         """Node test that matches any child element."""
         axis = 'child'
         def __call__(self, kind, *_):
-            if kind is Stream.START:
+            if kind is START:
                 return True
             return None
 
@@ -230,7 +228,7 @@
         def __init__(self, name):
             self.name = QName(name)
         def __call__(self, kind, data, _):
-            if kind is Stream.START:
+            if kind is START:
                 return data[0].localname == self.name
             return None
         def __repr__(self):
@@ -240,10 +238,10 @@
         """Node test that matches any attribute."""
         axis = 'attribute'
         def __call__(self, kind, data, pos):
-            if kind is Stream.START:
+            if kind is START:
                 text = ''.join([val for _, val in data[1]])
                 if text:
-                    return Stream.TEXT, text, pos
+                    return TEXT, text, pos
                 return None
             return None
 
@@ -253,9 +251,9 @@
         def __init__(self, name):
             self.name = QName(name)
         def __call__(self, kind, data, pos):
-            if kind is Stream.START:
+            if kind is START:
                 if self.name in data[1]:
-                    return Stream.TEXT, data[1].get(self.name), pos
+                    return TEXT, data[1].get(self.name), pos
                 return None
             return None
         def __repr__(self):
@@ -267,7 +265,7 @@
     class _FunctionText(_Function):
         """Function that returns text content."""
         def __call__(self, kind, data, pos):
-            if kind is Stream.TEXT:
+            if kind is TEXT:
                 return kind, data, pos
             return None
 
@@ -276,7 +274,7 @@
         def __init__(self, value):
             self.value = value
         def __call__(self, *_):
-            return Stream.TEXT, self.value, (-1, -1)
+            return TEXT, self.value, (-1, -1)
 
     class _OperatorEq(_NodeTest):
         """Equality comparison operator."""
--- a/markup/template.py
+++ b/markup/template.py
@@ -38,6 +38,12 @@
  * Could we generate byte code from expressions?
 """
 
+try:
+    from collections import deque
+except ImportError:
+    class deque(list):
+        def appendleft(self, x): self.insert(0, x)
+        def popleft(self): return self.pop(0)
 import compiler
 import os
 import posixpath
@@ -117,40 +123,35 @@
     """
 
     def __init__(self, **data):
-        self.stack = [data]
-
-    def __getitem__(self, key):
-        """Get a variable's value, starting at the current context frame and
-        going upward.
-        """
-        return self.get(key)
+        self.frames = deque([data])
 
     def __repr__(self):
-        return repr(self.stack)
+        return repr(self.frames)
 
     def __setitem__(self, key, value):
         """Set a variable in the current context."""
-        self.stack[0][key] = value
+        self.frames[0][key] = value
 
     def get(self, key):
         """Get a variable's value, starting at the current context frame and
         going upward.
         """
-        for frame in self.stack:
+        for frame in self.frames:
             if key in frame:
                 return frame[key]
+    __getitem__ = get
 
     def push(self, **data):
         """Push a new context frame on the stack."""
-        self.stack.insert(0, data)
+        self.frames.appendleft(data)
 
     def pop(self):
         """Pop the top-most context frame from the stack.
         
         If the stack is empty, an `AssertionError` is raised.
         """
-        assert self.stack, 'Pop from empty context stack'
-        self.stack.pop(0)
+        #assert self.frames, 'Pop from empty context stack'
+        self.frames.popleft()
 
 
 class Directive(object):
Copyright (C) 2012-2017 Edgewall Software