Index: third_party/cython/src/Cython/StringIOTree.py |
diff --git a/third_party/cython/src/Cython/StringIOTree.py b/third_party/cython/src/Cython/StringIOTree.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c41c3d6e8d008ca1168875de2dc0edb1d55a6f92 |
--- /dev/null |
+++ b/third_party/cython/src/Cython/StringIOTree.py |
@@ -0,0 +1,99 @@ |
+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 |
+ self.write = stream.write |
+ self.markers = [] |
+ |
+ def getvalue(self): |
+ content = [x.getvalue() for x in self.prepended_children] |
+ content.append(self.stream.getvalue()) |
+ return "".join(content) |
+ |
+ def copyto(self, target): |
+ """Potentially cheaper than getvalue as no string concatenation |
+ needs to happen.""" |
+ for child in self.prepended_children: |
+ child.copyto(target) |
+ stream_content = self.stream.getvalue() |
+ if stream_content: |
+ target.write(stream_content) |
+ |
+ def commit(self): |
+ # Save what we have written until now so that the buffer |
+ # itself is empty -- this makes it ready for insertion |
+ if self.stream.tell(): |
+ self.prepended_children.append(StringIOTree(self.stream)) |
+ self.prepended_children[-1].markers = self.markers |
+ self.markers = [] |
+ self.stream = StringIO() |
+ self.write = self.stream.write |
+ |
+ def insert(self, iotree): |
+ """ |
+ Insert a StringIOTree (and all of its contents) at this location. |
+ Further writing to self appears after what is inserted. |
+ """ |
+ self.commit() |
+ self.prepended_children.append(iotree) |
+ |
+ def insertion_point(self): |
+ """ |
+ Returns a new StringIOTree, which is left behind at the current position |
+ (it what is written to the result will appear right before whatever is |
+ next written to self). |
+ |
+ Calling getvalue() or copyto() on the result will only return the |
+ contents written to it. |
+ """ |
+ # Save what we have written until now |
+ # This is so that getvalue on the result doesn't include it. |
+ self.commit() |
+ # Construct the new forked object to return |
+ other = StringIOTree() |
+ self.prepended_children.append(other) |
+ return other |
+ |
+ def allmarkers(self): |
+ children = self.prepended_children |
+ return [m for c in children for m in c.allmarkers()] + self.markers |
+ |
+ |
+__doc__ = r""" |
+Implements a buffer with insertion points. When you know you need to |
+"get back" to a place and write more later, simply call insertion_point() |
+at that spot and get a new StringIOTree object that is "left behind". |
+ |
+EXAMPLE: |
+ |
+>>> a = StringIOTree() |
+>>> a.write('first\n') |
+>>> b = a.insertion_point() |
+>>> a.write('third\n') |
+>>> b.write('second\n') |
+>>> a.getvalue().split() |
+['first', 'second', 'third'] |
+ |
+>>> c = b.insertion_point() |
+>>> d = c.insertion_point() |
+>>> d.write('alpha\n') |
+>>> b.write('gamma\n') |
+>>> c.write('beta\n') |
+>>> b.getvalue().split() |
+['second', 'alpha', 'beta', 'gamma'] |
+>>> i = StringIOTree() |
+>>> d.insert(i) |
+>>> i.write('inserted\n') |
+>>> out = StringIO() |
+>>> a.copyto(out) |
+>>> out.getvalue().split() |
+['first', 'second', 'alpha', 'inserted', 'beta', 'gamma', 'third'] |
+""" |