+
+class page(pagetree):
+ """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, and `clen`,
+ being either an int describing the total number of bytes in the
+ stream, or None if the value is not known in advance."""
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *exc_info):
+ self.close()
+
+ def fileno(self):
+ """If reading the imgstream may block, fileno() should return
+ a file descriptor that can be polled. If fileno() returns
+ None, that should mean that reading will not block."""
+ return None
+
+ 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 cursor(object):
+ def __init__(self, ob):
+ if isinstance(ob, cursor):
+ self.cur = ob.cur
+ else:
+ self.cur = self.descend(ob)
+
+ def descend(self, ob, last=False):
+ while isinstance(ob, pagelist):
+ ob = ob[len(ob) - 1 if last else 0]
+ if not isinstance(ob, page):
+ raise TypeError("object in page tree was unexpectedly not a pagetree")
+ return ob
+
+ def next(self):
+ for n, i in reversed(self.cur.stack):
+ if i < len(n) - 1:
+ self.cur = self.descend(n[i + 1])
+ return self.cur
+ raise StopIteration()
+
+ def prev(self):
+ for n, i in reversed(self.cur.stack):
+ if i > 0:
+ self.cur = self.descend(n[i - 1], True)
+ return self.cur
+ raise StopIteration()
+
+ def __iter__(self):
+ return self
+
+def _lazymod(name):
+ return __import__(name, fromlist=["dummy"])
+class _lazydict(object):
+ def __init__(self):
+ self.bk = {}
+ def __setitem__(self, key, val):
+ self.bk[key] = "u", val
+ def __getitem__(self, key):
+ st, v = self.bk[key]
+ if st == "u":
+ v = self.bk[key] = v()
+ return v
+libraries = _lazydict()
+libraries["mf"] = lambda: _lazymod("manga.mangafox").library()