Added a proper pagestack to pagelists and pages.
[automanga.git] / manga / lib.py
CommitLineData
f3ad0817 1class library(object):
6a1e046b
FT
2 """Class representing a single source of multiple mangas."""
3
4 def byname(self, prefix):
5 """Returns an iterable object of all mangas in this library
6 whose names (case-insensitively) begin with the given
7 prefix.
8
9 All libraries should implement this."""
10 raise NotImplementedError()
11
12 def __iter__(self):
13 """Return an iterator of all known mangas in this library.
14
15 Not all libraries need implement this."""
16 raise NotImplementedError("manga.lib.library iterator")
f3ad0817 17
3683ab38
FT
18class pagetree(object):
19 """Base class for objects in the tree of pages and pagelists.
20
21 All pagetree objects should contain an attribute `stack', contains
22 a list of pairs. The last pair in the list should be the pagetree
23 object which yielded this pagetree object, along with the index
24 which yielded it. Every non-last pair should be the same
25 information for the pair following it. The only objects with empty
26 `stack' lists should be `manga' objects."""
27 pass
28
29class pagelist(pagetree):
6a1e046b
FT
30 """Class representing a list of either pages, or nested
31 pagelists. Might be, for instance, a volume or a chapter.
32
33 All pagelists should contain an attribute `name', containing some
34 human-readable Unicode representation of the pagelist."""
35
36 def __len__(self):
37 """Return the number of (direct) sub-nodes in this pagelist.
38
39 All pagelists need to implement this."""
40 raise NotImplementedError()
41
42 def __getitem__(self, idx):
43 """Return the direct sub-node of the given index in this
44 pagelist. Sub-node indexes are always zero-based and
45 contiguous, regardless of any gaps in the underlying medium,
46 which should be indicated instead by way of the `name'
47 attribute.
48
49 All pagelists need to implement this."""
50 raise NotImplementedError()
f3ad0817
FT
51
52class manga(pagelist):
6a1e046b
FT
53 """Class reprenting a single manga. Includes the pagelist class,
54 and all constraints valid for it."""
f3ad0817
FT
55 pass
56
3683ab38 57class page(pagetree):
6a1e046b
FT
58 """Class representing a single page of a manga. Pages make up the
59 leaf nodes of a pagelist tree.
60
61 All pages should contain an attribute `manga', referring back to
62 the containing manga instance."""
63
64 def open(self):
65 """Open a stream for the image this page represents. The
66 returned object should be an imgstream class.
67
68 All pages need to implement this."""
69 raise NotImplementedError()
70
71class imgstream(object):
72 """An open image I/O stream for a manga page. Generally, it should
73 be file-like. This base class implements the resource-manager
74 interface for use in `with' statements, calling close() on itself
75 when exiting the with-scope.
76
77 All imgstreams should contain an attribute `ctype', being the
78 Content-Type of the image being read by the stream."""
79
80 def __enter__(self):
81 return self
82
83 def __exit__(self, *exc_info):
84 self.close()
85
86 def close(self):
87 """Close this stream."""
88 raise NotImplementedError()
89
90 def read(self, sz = None):
91 """Read SZ bytes from the stream, or the entire rest of the
92 stream of SZ is not given."""
93 raise NotImplementedError()
07be272b
FT
94
95class pageiter(object):
96 def __init__(self, root):
97 self.nstack = [0]
98 self.lstack = [root]
99
100 def next(self):
101 while True:
102 if len(self.nstack) == 0:
103 raise StopIteration
104 try:
105 node = self.lstack[-1][self.nstack[-1]]
106 except IndexError:
107 self.lstack.pop()
108 self.nstack.pop()
109 if len(self.nstack) > 0:
110 self.nstack[-1] += 1
111 continue
112 if isinstance(node, page):
113 nl = tuple(self.nstack)
114 self.nstack[-1] += 1
115 return nl, node
116 elif isinstance(node, pagelist):
117 self.lstack.append(node)
118 self.nstack.append(0)
119
120 def __iter__(self):
121 return self