Commit | Line | Data |
---|---|---|
f3ad0817 | 1 | class 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 FT |
17 | |
18 | class pagelist(object): | |
6a1e046b FT |
19 | """Class representing a list of either pages, or nested |
20 | pagelists. Might be, for instance, a volume or a chapter. | |
21 | ||
22 | All pagelists should contain an attribute `name', containing some | |
23 | human-readable Unicode representation of the pagelist.""" | |
24 | ||
25 | def __len__(self): | |
26 | """Return the number of (direct) sub-nodes in this pagelist. | |
27 | ||
28 | All pagelists need to implement this.""" | |
29 | raise NotImplementedError() | |
30 | ||
31 | def __getitem__(self, idx): | |
32 | """Return the direct sub-node of the given index in this | |
33 | pagelist. Sub-node indexes are always zero-based and | |
34 | contiguous, regardless of any gaps in the underlying medium, | |
35 | which should be indicated instead by way of the `name' | |
36 | attribute. | |
37 | ||
38 | All pagelists need to implement this.""" | |
39 | raise NotImplementedError() | |
f3ad0817 FT |
40 | |
41 | class manga(pagelist): | |
6a1e046b FT |
42 | """Class reprenting a single manga. Includes the pagelist class, |
43 | and all constraints valid for it.""" | |
f3ad0817 FT |
44 | pass |
45 | ||
46 | class page(object): | |
6a1e046b FT |
47 | """Class representing a single page of a manga. Pages make up the |
48 | leaf nodes of a pagelist tree. | |
49 | ||
50 | All pages should contain an attribute `manga', referring back to | |
51 | the containing manga instance.""" | |
52 | ||
53 | def open(self): | |
54 | """Open a stream for the image this page represents. The | |
55 | returned object should be an imgstream class. | |
56 | ||
57 | All pages need to implement this.""" | |
58 | raise NotImplementedError() | |
59 | ||
60 | class imgstream(object): | |
61 | """An open image I/O stream for a manga page. Generally, it should | |
62 | be file-like. This base class implements the resource-manager | |
63 | interface for use in `with' statements, calling close() on itself | |
64 | when exiting the with-scope. | |
65 | ||
66 | All imgstreams should contain an attribute `ctype', being the | |
67 | Content-Type of the image being read by the stream.""" | |
68 | ||
69 | def __enter__(self): | |
70 | return self | |
71 | ||
72 | def __exit__(self, *exc_info): | |
73 | self.close() | |
74 | ||
75 | def close(self): | |
76 | """Close this stream.""" | |
77 | raise NotImplementedError() | |
78 | ||
79 | def read(self, sz = None): | |
80 | """Read SZ bytes from the stream, or the entire rest of the | |
81 | stream of SZ is not given.""" | |
82 | raise NotImplementedError() | |
07be272b FT |
83 | |
84 | class pageiter(object): | |
85 | def __init__(self, root): | |
86 | self.nstack = [0] | |
87 | self.lstack = [root] | |
88 | ||
89 | def next(self): | |
90 | while True: | |
91 | if len(self.nstack) == 0: | |
92 | raise StopIteration | |
93 | try: | |
94 | node = self.lstack[-1][self.nstack[-1]] | |
95 | except IndexError: | |
96 | self.lstack.pop() | |
97 | self.nstack.pop() | |
98 | if len(self.nstack) > 0: | |
99 | self.nstack[-1] += 1 | |
100 | continue | |
101 | if isinstance(node, page): | |
102 | nl = tuple(self.nstack) | |
103 | self.nstack[-1] += 1 | |
104 | return nl, node | |
105 | elif isinstance(node, pagelist): | |
106 | self.lstack.append(node) | |
107 | self.nstack.append(0) | |
108 | ||
109 | def __iter__(self): | |
110 | return self |