Added StringIOTree class
authorDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Tue, 29 Jul 2008 14:11:25 +0000 (16:11 +0200)
committerDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Tue, 29 Jul 2008 14:11:25 +0000 (16:11 +0200)
Cython/StringIOTree.py [new file with mode: 0644]

diff --git a/Cython/StringIOTree.py b/Cython/StringIOTree.py
new file mode 100644 (file)
index 0000000..325c0e2
--- /dev/null
@@ -0,0 +1,93 @@
+from cStringIO import StringIO
+
+class StringIOTree(object):
+    """
+    See module docs.
+    """
+
+    def __init__(self, stream=None):
+        self.prepended_children = []
+        if stream is None: stream = StringIO()
+        self.stream = stream
+
+    def getvalue(self):
+        return ("".join([x.getvalue() for x in self.prepended_children]) +
+                self.stream.getvalue())
+
+    def copyto(self, target):
+        """Potentially cheaper than getvalue as no string concatenation
+        needs to happen."""
+        for child in self.prepended_children:
+            child.copyto(target)
+        target.write(self.stream.getvalue())
+
+    def write(self, what):
+        self.stream.write(what)
+
+    def fork(self, count=2):
+        # Shuffle around the embedded StringIO objects so that
+        # references to self keep writing at the end.
+        self.prepended_children.append(StringIOTree(self.stream))
+        self.stream = StringIO()
+        tines = [StringIOTree() for i in range(1, count)]
+        self.prepended_children.extend(tines)
+        tines.append(self)
+        return tines
+
+__doc__ = r"""
+Implements a forkable buffer. When you know you need to "get back" to a place
+and write more later, simply call fork() and get.
+
+The last buffer returned from fork() will always be the object itself; i.e.,
+if code elsewhere has references to the buffer and writes to it later it will
+always end up at the end just as if the fork never happened.
+
+
+EXAMPLE:
+
+>>> a = StringIOTree()
+>>> a.write('first\n')
+>>> b, c = a.fork()
+>>> c.write('third\n')
+>>> b.write('second\n')
+>>> print a.getvalue()
+first
+second
+third
+<BLANKLINE>
+
+>>> a.write('fourth\n')
+>>> print a.getvalue()
+first
+second
+third
+fourth
+<BLANKLINE>
+
+>>> d, e, f = b.fork(3)
+>>> d.write('alpha\n')
+>>> f.write('gamma\n')
+>>> e.write('beta\n')
+>>> print b.getvalue()
+second
+alpha
+beta
+gamma
+<BLANKLINE>
+
+>>> out = StringIO()
+>>> a.copyto(out)
+>>> print out.getvalue()
+first
+second
+alpha
+beta
+gamma
+third
+fourth
+<BLANKLINE>
+"""
+            
+if __name__ == "__main__":
+    import doctest
+    doctest.testmod()