+ """Class representing a single page of a manga. Pages make up the
+ leaf nodes of a pagelist tree.
+
+ All pages should contain an attribute `manga', referring back to
+ the containing manga instance."""
+
+ def open(self):
+ """Open a stream for the image this page represents. The
+ returned object should be an imgstream class.
+
+ All pages need to implement this."""
+ raise NotImplementedError()
+
+class imgstream(object):
+ """An open image I/O stream for a manga page. Generally, it should
+ be file-like. This base class implements the resource-manager
+ interface for use in `with' statements, calling close() on itself
+ when exiting the with-scope.
+
+ All imgstreams should contain an attribute `ctype', being the
+ Content-Type of the image being read by the stream."""
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *exc_info):
+ self.close()
+
+ def close(self):
+ """Close this stream."""
+ raise NotImplementedError()
+
+ def read(self, sz = None):
+ """Read SZ bytes from the stream, or the entire rest of the
+ stream of SZ is not given."""
+ raise NotImplementedError()
+
+class pageiter(object):
+ def __init__(self, root):
+ self.nstack = [0]
+ self.lstack = [root]
+
+ def next(self):
+ while True:
+ if len(self.nstack) == 0:
+ raise StopIteration
+ try:
+ node = self.lstack[-1][self.nstack[-1]]
+ except IndexError:
+ self.lstack.pop()
+ self.nstack.pop()
+ if len(self.nstack) > 0:
+ self.nstack[-1] += 1
+ continue
+ if isinstance(node, page):
+ nl = tuple(self.nstack)
+ self.nstack[-1] += 1
+ return nl, node
+ elif isinstance(node, pagelist):
+ self.lstack.append(node)
+ self.nstack.append(0)
+
+ def __iter__(self):
+ return self